Skip to content

Commit 326677c

Browse files
committed
A bit of Sendable work (WIP)
1 parent 9c0ffa9 commit 326677c

10 files changed

Lines changed: 89 additions & 50 deletions

‎Package.resolved‎

Lines changed: 38 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Package.swift‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ let package = Package(
1212
],
1313
dependencies: [
1414
.package(url: "https://github.com/apple/swift-atomics.git", from: "1.2.0"),
15-
.package(url: "https://github.com/apple/swift-collections", from: "1.1.0"),
16-
.package(url: "https://github.com/vapor/postgres-nio.git", from: "1.20.2"),
17-
.package(url: "https://github.com/vapor/postgres-kit", from: "2.12.3"),
15+
.package(url: "https://github.com/apple/swift-collections", from: "1.1.1"),
16+
.package(url: "https://github.com/vapor/postgres-nio.git", from: "1.21.4"),
17+
.package(url: "https://github.com/vapor/postgres-kit", from: "2.13.5"),
1818
],
1919
targets: [
2020
.target(
@@ -30,4 +30,5 @@ let package = Package(
3030
dependencies: [
3131
.target(name: "PostgresConnectionPool"),
3232
]),
33-
])
33+
]
34+
)

‎Sources/PostgresConnectionPool/Extensions/PSQLError+Description.swift‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,20 @@ import PostgresNIO
77

88
// MARK: CustomStringConvertible
99

10-
extension PSQLError: CustomStringConvertible {
10+
extension PSQLError {
1111

1212
/// A short error description.
13-
public var description: String {
13+
public var pgPoolDescription: String {
1414
if let serverInfo = self.serverInfo,
1515
let severity = serverInfo[.severity],
1616
let message = serverInfo[.message]
1717
{
18-
return "<PSQLError: \(severity): \(message)>"
18+
if let code = serverInfo[.sqlState] {
19+
return "<PSQLError (code \(code)): \(severity): \(message)>"
20+
}
21+
else {
22+
return "<PSQLError: \(severity): \(message)>"
23+
}
1924
}
2025

2126
return "<PSQLError: \(self.code.description)>"
@@ -25,10 +30,10 @@ extension PSQLError: CustomStringConvertible {
2530

2631
// MARK: - CustomDebugStringConvertible
2732

28-
extension PSQLError: CustomDebugStringConvertible {
33+
extension PSQLError {
2934

3035
/// A detailed error description suitable for debugging queries and other problems with the server.
31-
public var debugDescription: String {
36+
public var pgPoolDebugDescription: String {
3237
var messageElements: [String] = [
3338
"code: \(self.code)"
3439
]

‎Sources/PostgresConnectionPool/PoolConfiguration.swift‎

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Foundation
66
import PostgresNIO
77

88
/// Settings for the pool like connection parameters.
9-
public struct PoolConfiguration {
9+
public struct PoolConfiguration: Sendable {
1010

1111
/// PostgreSQL connection parameters.
1212
@available(*, deprecated, message: "Use `PostgresConnection.Configuration` etc. instead.")
@@ -57,15 +57,15 @@ public struct PoolConfiguration {
5757
/// Called when new connections to the database are openend.
5858
///
5959
/// Use this to set extra connection options or override the defaults.
60-
public var onOpenConnection: ((PostgresConnection, Logger) async throws -> Void)?
60+
public let onOpenConnection: (@Sendable (PostgresConnection, Logger) async throws -> Void)?
6161

6262
/// Called before a connection is given to a client.
6363
///
6464
/// Default is to do a quick connection check with "SELECT 1" and close the connection on errors.
65-
public var onReturnConnection: ((PostgresConnection, Logger) async throws -> Void)?
65+
public let onReturnConnection: (@Sendable (PostgresConnection, Logger) async throws -> Void)?
6666

6767
/// Called just before a connection is being closed.
68-
public var onCloseConnection: ((PostgresConnection, Logger) async throws -> Void)?
68+
public let onCloseConnection: (@Sendable (PostgresConnection, Logger) async throws -> Void)?
6969

7070
/// Pool configuation.
7171
///
@@ -76,14 +76,20 @@ public struct PoolConfiguration {
7676
/// - queryTimeout: TImeout for individual database queries
7777
/// - poolSize: The maximum number of open connections
7878
/// - maxIdleConnections: The maximum number of idle connections
79+
/// - onOpenConnection: Called when new connections to the database are openend
80+
/// - onReturnConnection: Called before a connection is given to a client
81+
/// - onCloseConnection: Called just before a connection is being closed
7982
public init(
8083
applicationName: String,
8184
postgresConfiguration: PostgresConnection.Configuration,
8285
connectTimeout: TimeInterval = 5.0,
8386
connectionRetryInterval: TimeInterval = 0.5,
8487
queryTimeout: TimeInterval? = nil,
8588
poolSize: Int = 10,
86-
maxIdleConnections: Int? = nil)
89+
maxIdleConnections: Int? = nil,
90+
onOpenConnection: (@Sendable (PostgresConnection, Logger) async throws -> Void)? = nil,
91+
onReturnConnection: (@Sendable (PostgresConnection, Logger) async throws -> Void)? = nil,
92+
onCloseConnection: (@Sendable (PostgresConnection, Logger) async throws -> Void)? = nil)
8793
{
8894
self.applicationName = applicationName
8995
self.postgresConfiguration = postgresConfiguration
@@ -93,9 +99,11 @@ public struct PoolConfiguration {
9399
self.poolSize = poolSize.atLeast(1)
94100
self.maxIdleConnections = maxIdleConnections?.atLeast(0)
95101

96-
self.onReturnConnection = { connection, logger in
102+
self.onOpenConnection = onOpenConnection
103+
self.onReturnConnection = onReturnConnection ?? { connection, logger in
97104
try await connection.query("SELECT 1", logger: logger)
98105
}
106+
self.onCloseConnection = onCloseConnection
99107
}
100108

101109
@available(*, deprecated, message: "Use `init(applicationName:postgresConfiguration:connectTimeout:queryTimeout:poolSize:maxIdleConnections:)` instead.")

‎Sources/PostgresConnectionPool/PoolConnection.swift‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import PostgresNIO
99
final class PoolConnection: Identifiable, Equatable {
1010

1111
// For connection ids
12-
private static let atomic: ManagedAtomic<Int> = .init(0)
12+
private static let connectionId: ManagedAtomic<Int> = .init(0)
1313

14-
private(set) var usageCounter = 0
14+
let usageCounter: ManagedAtomic<Int> = .init(0)
1515

1616
let id: Int
1717
var batchId: Int?
@@ -20,7 +20,7 @@ final class PoolConnection: Identifiable, Equatable {
2020
var state: PoolConnectionState = .connecting {
2121
didSet {
2222
if case .active = state {
23-
usageCounter += 1
23+
usageCounter.wrappingIncrement(by: 1, ordering: .relaxed)
2424
}
2525
}
2626
}
@@ -37,7 +37,7 @@ final class PoolConnection: Identifiable, Equatable {
3737
}
3838

3939
init() {
40-
self.id = PoolConnection.atomic.loadThenWrappingIncrement(by: 1, ordering: .relaxed)
40+
self.id = PoolConnection.connectionId.loadThenWrappingIncrement(by: 1, ordering: .relaxed)
4141
}
4242

4343
static func == (lhs: PoolConnection, rhs: PoolConnection) -> Bool {

‎Sources/PostgresConnectionPool/PoolConnectionState.swift‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import Foundation
66

77
/// The possible states of a database connection.
8-
public enum PoolConnectionState: Equatable {
8+
public enum PoolConnectionState: Equatable, Sendable {
99

1010
/// The connection is in use.
1111
case active(Date)

‎Sources/PostgresConnectionPool/PoolError.swift‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Foundation
66
import PostgresNIO
77

88
/// Possible errors from the connection pool.
9-
public enum PoolError: Error {
9+
public enum PoolError: Error, Sendable {
1010

1111
/// The request was cancelled.
1212
case cancelled

‎Sources/PostgresConnectionPool/PoolInfo.swift‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import Foundation
66
import PostgresNIO
77

88
/// General information about the pool and its open connections.
9-
public struct PoolInfo {
9+
public struct PoolInfo: Sendable {
1010

1111
/// Information about an open connection.
12-
public struct ConnectionInfo {
12+
public struct ConnectionInfo: Sendable {
1313
/// The unique connection id.
1414
public let id: Int
1515
/// The connection name on the server.

‎Sources/PostgresConnectionPool/PostgresConnectionPool.swift‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ public actor PostgresConnectionPool {
263263
return PoolInfo.ConnectionInfo(
264264
id: connection.id,
265265
name: nameForConnection(id: connection.id),
266-
usageCounter: connection.usageCounter,
266+
usageCounter: connection.usageCounter.load(ordering: .relaxed),
267267
batchId: connection.batchId,
268268
query: connection.query,
269269
queryRuntime: connection.queryRuntime,
@@ -323,7 +323,7 @@ public actor PostgresConnectionPool {
323323
|| (connection.state != .connecting && connection.connection?.isClosed ?? false)
324324
})
325325

326-
let usageCounter = connections.reduce(0) { $0 + $1.usageCounter }
326+
let usageCounter = connections.reduce(0) { $0 + $1.usageCounter.load(ordering: .relaxed) }
327327
logger.debug("[\(poolName)] \(connections.count) connections (\(available.count) available, \(usageCounter) queries), \(continuations.count) continuations left")
328328

329329
// Check for waiting continuations and open a new connection if possible

‎Sources/PostgresConnectionPool/PostgresConnectionWrapper.swift‎

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,13 @@ public final class PostgresConnectionWrapper {
8989
}
9090

9191
public func sql(
92-
encoder: PostgresDataEncoder = PostgresDataEncoder(),
93-
decoder: PostgresDataDecoder = PostgresDataDecoder())
94-
-> SQLDatabase
92+
encodingContext: PostgresEncodingContext<some PostgresJSONEncoder> = .default,
93+
decodingContext: PostgresDecodingContext<some PostgresJSONDecoder> = .default,
94+
queryLogLevel: Logger.Level? = .debug)
95+
-> some SQLDatabase
9596
{
9697
// TODO: Track the current query
97-
postgresConnection.sql(encoder: encoder, decoder: decoder)
98+
postgresConnection.sql(encodingContext: encodingContext, decodingContext: decodingContext, queryLogLevel: queryLogLevel)
9899
}
99100

100101
/// Add a handler for NotificationResponse messages on a certain channel.
@@ -105,11 +106,17 @@ public final class PostgresConnectionWrapper {
105106
@discardableResult
106107
public func addListener(
107108
channel: String,
108-
handler notificationHandler: @escaping (PostgresListenContext, PostgresMessage.NotificationResponse) -> Void)
109+
handler notificationHandler: @Sendable @escaping (PostgresListenContext, PostgresMessage.NotificationResponse) -> Void)
109110
-> PostgresListenContext
110111
{
111112
poolConnection.query = "LISTEN \(channel)"
112113
return postgresConnection.addListener(channel: channel, handler: notificationHandler)
113114
}
114115

116+
/// Start listening for a channel
117+
public func listen(_ channel: String) async throws -> PostgresNotificationSequence {
118+
poolConnection.query = "LISTEN \(channel)"
119+
return try await postgresConnection.listen(channel)
120+
}
121+
115122
}

0 commit comments

Comments
 (0)