Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ jobs:
fail-fast: false
matrix:
swift-image:
- swift:5.10-jammy
- swift:6.0-noble
- swift:6.0-jammy
- swift:6.1-noble
- swiftlang/swift:nightly-6.2-noble
- swift:6.2-noble
- swiftlang/swift:nightly-main-noble
container: ${{ matrix.swift-image }}
runs-on: ubuntu-latest
Expand Down Expand Up @@ -64,7 +63,7 @@ jobs:
- postgres-image: postgres:13
postgres-auth: trust
container:
image: swift:6.1-noble
image: swift:6.2-noble
volumes: [ 'pgrunshare:/var/run/postgresql' ]
runs-on: ubuntu-latest
env:
Expand Down
10 changes: 8 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
// swift-tools-version:5.10
// swift-tools-version:6.0
import PackageDescription

#if compiler(>=6.1)
let swiftSettings: [SwiftSetting] = []
#else
let swiftSettings: [SwiftSetting] = [
.enableUpcomingFeature("StrictConcurrency"),
// Sadly the 6.0 compiler concurrency checker finds false positives.
// To be able to compile, lets reduce the language version down to 5 for 6.0 only.
.swiftLanguageMode(.v5)
]
#endif

let package = Package(
name: "postgres-nio",
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<img src="https://img.shields.io/github/actions/workflow/status/vapor/postgres-nio/test.yml?event=push&style=plastic&logo=github&label=tests&logoColor=%23ccc" alt="Continuous Integration">
</a>
<a href="https://swift.org">
<img src="https://design.vapor.codes/images/swift510up.svg" alt="Swift 5.10+">
<img src="https://design.vapor.codes/images/swift60up.svg" alt="Swift 6.0+">
</a>
<a href="https://www.swift.org/sswg/incubation-process.html">
<img src="https://design.vapor.codes/images/sswg-graduated.svg" alt="SSWG Incubation Level: Graduated">
Expand Down Expand Up @@ -163,7 +163,7 @@ Please see [SECURITY.md] for details on the security process.
[Team Chat]: https://discord.gg/vapor
[MIT License]: LICENSE
[Continuous Integration]: https://github.com/vapor/postgres-nio/actions
[Swift 5.10]: https://swift.org
[Swift 6.0]: https://swift.org
[Security.md]: https://github.com/vapor/.github/blob/main/SECURITY.md

[`PostgresConnection`]: https://api.vapor.codes/postgresnio/documentation/postgresnio/postgresconnection
Expand Down
57 changes: 2 additions & 55 deletions Sources/PostgresNIO/Connection/PostgresConnection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,6 @@ extension PostgresConnection {
}
}

#if compiler(>=6.0)
/// Puts the connection into an open transaction state, for the provided `closure`'s lifetime.
///
/// The function starts a transaction by running a `BEGIN` query on the connection against the database. It then
Expand All @@ -552,9 +551,8 @@ extension PostgresConnection {
file: String = #file,
line: Int = #line,
isolation: isolated (any Actor)? = #isolation,
// DO NOT FIX THE WHITESPACE IN THE NEXT LINE UNTIL 5.10 IS UNSUPPORTED
// https://github.com/swiftlang/swift/issues/79285
_ process: (PostgresConnection) async throws -> sending Result) async throws -> sending Result {
_ process: (PostgresConnection) async throws -> sending Result
) async throws -> sending Result {
do {
try await self.query("BEGIN;", logger: logger)
} catch {
Expand Down Expand Up @@ -583,57 +581,6 @@ extension PostgresConnection {
throw transactionError
}
}
#else
/// Puts the connection into an open transaction state, for the provided `closure`'s lifetime.
///
/// The function starts a transaction by running a `BEGIN` query on the connection against the database. It then
/// lends the connection to the user provided closure. The user can then modify the database as they wish. If the user
/// provided closure returns successfully, the function will attempt to commit the changes by running a `COMMIT`
/// query against the database. If the user provided closure throws an error, the function will attempt to rollback the
/// changes made within the closure.
///
/// - Parameters:
/// - logger: The `Logger` to log into for the transaction.
/// - file: The file, the transaction was started in. Used for better error reporting.
/// - line: The line, the transaction was started in. Used for better error reporting.
/// - closure: The user provided code to modify the database. Use the provided connection to run queries.
/// The connection must stay in the transaction mode. Otherwise this method will throw!
/// - Returns: The closure's return value.
public func withTransaction<Result>(
logger: Logger,
file: String = #file,
line: Int = #line,
_ process: (PostgresConnection) async throws -> Result
) async throws -> Result {
do {
try await self.query("BEGIN;", logger: logger)
} catch {
throw PostgresTransactionError(file: file, line: line, beginError: error)
}

var closureHasFinished: Bool = false
do {
let value = try await process(self)
closureHasFinished = true
try await self.query("COMMIT;", logger: logger)
return value
} catch {
var transactionError = PostgresTransactionError(file: file, line: line)
if !closureHasFinished {
transactionError.closureError = error
do {
try await self.query("ROLLBACK;", logger: logger)
} catch {
transactionError.rollbackError = error
}
} else {
transactionError.commitError = error
}

throw transactionError
}
}
#endif
}

// MARK: EventLoopFuture interface
Expand Down
12 changes: 8 additions & 4 deletions Sources/PostgresNIO/New/VariadicGenerics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ extension PostgresRow {
extension AsyncSequence where Element == PostgresRow {
// --- snip TODO: Remove once bug is fixed, that disallows tuples of one
@inlinable
public func decode<Column: PostgresDecodable>(
@preconcurrency
public func decode<Column: PostgresDecodable & Sendable>(
_: Column.Type,
context: PostgresDecodingContext<some PostgresJSONDecoder>,
file: String = #fileID,
Expand All @@ -128,7 +129,8 @@ extension AsyncSequence where Element == PostgresRow {
}

@inlinable
public func decode<Column: PostgresDecodable>(
@preconcurrency
public func decode<Column: PostgresDecodable & Sendable>(
_: Column.Type,
file: String = #fileID,
line: Int = #line
Expand All @@ -137,7 +139,8 @@ extension AsyncSequence where Element == PostgresRow {
}
// --- snap TODO: Remove once bug is fixed, that disallows tuples of one

public func decode<each Column: PostgresDecodable>(
@preconcurrency
public func decode<each Column: PostgresDecodable & Sendable>(
_ columnType: (repeat each Column).Type,
context: PostgresDecodingContext<some PostgresJSONDecoder>,
file: String = #fileID,
Expand All @@ -148,7 +151,8 @@ extension AsyncSequence where Element == PostgresRow {
}
}

public func decode<each Column: PostgresDecodable>(
@preconcurrency
public func decode<each Column: PostgresDecodable & Sendable>(
_ columnType: (repeat each Column).Type,
file: String = #fileID,
line: Int = #line
Expand Down
44 changes: 7 additions & 37 deletions Sources/PostgresNIO/Pool/PostgresClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -308,17 +308,15 @@ public final class PostgresClient: Sendable, ServiceLifecycle.Service {
return try await closure(lease.connection)
}

#if compiler(>=6.0)
/// Lease a connection for the provided `closure`'s lifetime.
///
/// - Parameter closure: A closure that uses the passed `PostgresConnection`. The closure **must not** capture
/// the provided `PostgresConnection`.
/// - Returns: The closure's return value.
public func withConnection<Result>(
isolation: isolated (any Actor)? = #isolation,
// DO NOT FIX THE WHITESPACE IN THE NEXT LINE UNTIL 5.10 IS UNSUPPORTED
// https://github.com/swiftlang/swift/issues/79285
_ closure: (PostgresConnection) async throws -> sending Result) async throws -> sending Result {
_ closure: (PostgresConnection) async throws -> sending Result
) async throws -> sending Result {
let lease = try await self.leaseConnection()

defer { lease.release() }
Expand Down Expand Up @@ -346,41 +344,13 @@ public final class PostgresClient: Sendable, ServiceLifecycle.Service {
file: String = #file,
line: Int = #line,
isolation: isolated (any Actor)? = #isolation,
// DO NOT FIX THE WHITESPACE IN THE NEXT LINE UNTIL 5.10 IS UNSUPPORTED
// https://github.com/swiftlang/swift/issues/79285
_ closure: (PostgresConnection) async throws -> sending Result) async throws -> sending Result {
try await self.withConnection { connection in
try await connection.withTransaction(logger: logger, file: file, line: line, closure)
_ closure: (PostgresConnection) async throws -> sending Result
) async throws -> sending Result {
// for 6.0 to compile we need to explicitly forward the isolation.
try await self.withConnection(isolation: isolation) { connection in
try await connection.withTransaction(logger: logger, file: file, line: line, isolation: isolation, closure)
}
}
#else

/// Lease a connection, which is in an open transaction state, for the provided `closure`'s lifetime.
///
/// The function leases a connection from the underlying connection pool and starts a transaction by running a `BEGIN`
/// query on the leased connection against the database. It then lends the connection to the user provided closure.
/// The user can then modify the database as they wish. If the user provided closure returns successfully, the function
/// will attempt to commit the changes by running a `COMMIT` query against the database. If the user provided closure
/// throws an error, the function will attempt to rollback the changes made within the closure.
///
/// - Parameters:
/// - logger: The `Logger` to log into for the transaction.
/// - file: The file, the transaction was started in. Used for better error reporting.
/// - line: The line, the transaction was started in. Used for better error reporting.
/// - closure: The user provided code to modify the database. Use the provided connection to run queries.
/// The connection must stay in the transaction mode. Otherwise this method will throw!
/// - Returns: The closure's return value.
public func withTransaction<Result>(
logger: Logger,
file: String = #file,
line: Int = #line,
_ closure: (PostgresConnection) async throws -> Result
) async throws -> Result {
try await self.withConnection { connection in
try await connection.withTransaction(logger: logger, file: file, line: line, closure)
}
}
#endif

/// Run a query on the Postgres server the client is connected to.
///
Expand Down
Loading