Skip to content

Commit 4cc5a2d

Browse files
authored
Merge pull request #6 from Outdooractive/3_postgres_connection
#3: Use PostgresConnection.Configuration for the PostgreSQL connection configuration
2 parents e4e086a + 0c7fa8a commit 4cc5a2d

File tree

7 files changed

+91
-22
lines changed

7 files changed

+91
-22
lines changed

README.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ This package requires Swift 5.7 or higher (at least Xcode 13), and compiles on m
1313

1414
```swift
1515
dependencies: [
16-
.package(url: "https://github.com/Outdooractive/PostgresConnectionPool.git", from: "0.5.4"),
16+
.package(url: "https://github.com/Outdooractive/PostgresConnectionPool.git", from: "0.5.5"),
1717
],
1818
targets: [
1919
.target(name: "MyTarget", dependencies: [
@@ -29,19 +29,21 @@ Please see also the [API documentation](https://swiftpackageindex.com/Outdooract
2929
``` swift
3030
import PostgresConnectionPool
3131
import PostgresKit
32+
import PostgresNIO
3233

3334
var logger = Logger(label: "TestApp")
3435
logger.logLevel = .debug
3536

36-
let connection = PoolConfiguration.Connection(
37-
username: "testuser",
38-
password: "testpassword",
37+
let postgresConfiguration = PostgresConnection.Configuration(
3938
host: "postgres",
4039
port: 5432,
41-
database: "test")
40+
username: "testuser",
41+
password: "testpassword",
42+
database: "test",
43+
tls: .disable)
4244
let configuration = PoolConfiguration(
4345
applicationName: "TestApp",
44-
connection: connection,
46+
postgresConfiguration: postgresConfiguration,
4547
connectTimeout: 10.0,
4648
queryTimeout: 60.0,
4749
poolSize: 5,

Sources/PostgresConnectionPool/PoolConfiguration.swift

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import PostgresNIO
99
public struct PoolConfiguration {
1010

1111
/// PostgreSQL connection parameters.
12+
@available(*, deprecated, message: "Use `PostgresConnection.Configuration` etc. instead.")
1213
public struct Connection {
1314
let username: String
1415
let password: String
@@ -35,12 +36,13 @@ public struct PoolConfiguration {
3536
public let applicationName: String
3637

3738
/// Connection parameters to the database.
38-
public let connection: Connection
39+
public let postgresConfiguration: PostgresConnection.Configuration
3940

4041
/// Timeout for opening new connections to the PostgreSQL database, in seconds (default: 5 seconds).
4142
public let connectTimeout: TimeInterval
4243

4344
/// TImeout for individual database queries, in seconds (default: none).
45+
/// - warning: This includes the time the server needs to send the data to the client, so be careful over slow connections.
4446
public let queryTimeout: TimeInterval?
4547

4648
/// The maximum number of open connections to the database (default: 10).
@@ -62,16 +64,25 @@ public struct PoolConfiguration {
6264
/// Called just before a connection is being closed.
6365
public var onCloseConnection: ((PostgresConnection, Logger) async throws -> Void)?
6466

67+
/// Pool configuation.
68+
///
69+
/// - Parameters:
70+
/// - applicationName: The name used for database connections
71+
/// - postgresConfiguration: Connection parameters to the database
72+
/// - connectTimeout: Timeout for opening new connections
73+
/// - queryTimeout: TImeout for individual database queries
74+
/// - poolSize: The maximum number of open connections
75+
/// - maxIdleConnections: The maximum number of idle connections
6576
public init(
6677
applicationName: String,
67-
connection: Connection,
78+
postgresConfiguration: PostgresConnection.Configuration,
6879
connectTimeout: TimeInterval = 5.0,
6980
queryTimeout: TimeInterval? = nil,
7081
poolSize: Int = 10,
7182
maxIdleConnections: Int? = nil)
7283
{
7384
self.applicationName = applicationName
74-
self.connection = connection
85+
self.postgresConfiguration = postgresConfiguration
7586
self.connectTimeout = connectTimeout.atLeast(1.0)
7687
self.queryTimeout = queryTimeout?.atLeast(1.0)
7788
self.poolSize = poolSize.atLeast(1)
@@ -82,4 +93,28 @@ public struct PoolConfiguration {
8293
}
8394
}
8495

96+
@available(*, deprecated, message: "Use `init(applicationName:postgresConfiguration:connectTimeout:queryTimeout:poolSize:maxIdleConnections:)` instead.")
97+
public init(
98+
applicationName: String,
99+
connection: Connection,
100+
connectTimeout: TimeInterval = 5.0,
101+
queryTimeout: TimeInterval? = nil,
102+
poolSize: Int = 10,
103+
maxIdleConnections: Int? = nil)
104+
{
105+
let postgresConfiguration = PostgresConnection.Configuration(
106+
host: connection.host,
107+
port: connection.port,
108+
username: connection.username,
109+
password: connection.password,
110+
database: connection.database,
111+
tls: .disable)
112+
self.init(applicationName: applicationName,
113+
postgresConfiguration: postgresConfiguration,
114+
connectTimeout: connectTimeout,
115+
queryTimeout: queryTimeout,
116+
poolSize: poolSize,
117+
maxIdleConnections: maxIdleConnections)
118+
}
119+
85120
}

Sources/PostgresConnectionPool/PoolConnectionState.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import Foundation
66

7+
/// The possible states of a database connection.
78
public enum PoolConnectionState: Equatable {
89

910
/// The connection is in use.

Sources/PostgresConnectionPool/PoolError.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public enum PoolError: Error {
1414
case connectionFailed
1515
/// The pool was already shut down.
1616
case poolDestroyed
17-
/// Some PostgreSQL error
17+
/// Some PostgreSQL error.
1818
case postgresError(PSQLError)
1919
/// The query was cancelled by the server.
2020
case queryCancelled(query: String, runtime: Double)

Sources/PostgresConnectionPool/PoolInfo.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,32 @@ public struct PoolInfo {
99

1010
/// Information about an open connection.
1111
public struct ConnectionInfo {
12+
/// The unique connection id.
1213
public let id: Int
14+
/// The connection name on the server.
1315
public let name: String
16+
/// Total number of queries that were sent over this connection.
1417
public let usageCounter: Int
18+
/// The current query, if available.
1519
public let query: String?
20+
/// The current time for the query, if available.
1621
public let queryRuntime: TimeInterval?
22+
/// The state of the connection, see ``PoolConnectionState``.
1723
public let state: PoolConnectionState
1824
}
1925

26+
/// The name of the pool which is usually something like the Postgres connection string.
2027
public let name: String
28+
/// The total number of open connections to the server.
2129
public let openConnections: Int
30+
/// The number of connections that are currently in use.
2231
public let activeConnections: Int
32+
/// The number of connections that are currently available.
2333
public let availableConnections: Int
34+
/// The total number of queries that were sent to the server.
2435
public let usageCounter: Int
2536

37+
/// Information about individual open connections to the server.
2638
public let connections: [ConnectionInfo]
2739

2840
}

Sources/PostgresConnectionPool/PostgresConnectionPool.swift

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,22 +48,32 @@ public actor PostgresConnectionPool {
4848
self.eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: configuration.poolSize * 2)
4949

5050
self.connectionName = String(configuration.applicationName.replacingPattern("[^-\\w\\d\\s()]", with: "").prefix(PostgresConnectionPool.postgresMaxNameLength))
51-
self.poolName = "\(configuration.connection.username)@\(configuration.connection.host):\(configuration.connection.port)/\(configuration.connection.database)"
5251
self.poolSize = configuration.poolSize
5352
self.maxIdleConnections = configuration.maxIdleConnections
5453
self.queryTimeout = configuration.queryTimeout
5554

55+
let dbUsername = configuration.postgresConfiguration.username
56+
let dbDatabase = configuration.postgresConfiguration.database ?? dbUsername
57+
if let host = configuration.postgresConfiguration.host,
58+
let port = configuration.postgresConfiguration.port
59+
{
60+
self.poolName = "\(dbUsername)@\(host):\(port)/\(dbDatabase)"
61+
}
62+
else if let unixSocketPath = configuration.postgresConfiguration.unixSocketPath {
63+
self.poolName = "postgresql:///\(dbDatabase)?user=\(dbUsername)&host=\(unixSocketPath)"
64+
}
65+
else if let channel = configuration.postgresConfiguration.establishedChannel {
66+
self.poolName = "\(dbUsername)@EstablishedChannel<\(channel)>/\(dbDatabase)"
67+
}
68+
else {
69+
self.poolName = "<Unknown connection>"
70+
}
71+
5672
self.onOpenConnection = configuration.onOpenConnection
5773
self.onReturnConnection = configuration.onReturnConnection
5874
self.onCloseConnection = configuration.onCloseConnection
5975

60-
var postgresConfiguration = PostgresConnection.Configuration(
61-
host: configuration.connection.host,
62-
port: configuration.connection.port,
63-
username: configuration.connection.username,
64-
password: configuration.connection.password,
65-
database: configuration.connection.database,
66-
tls: .disable)
76+
var postgresConfiguration = configuration.postgresConfiguration
6777
postgresConfiguration.options.connectTimeout = .seconds(Int64(configuration.connectTimeout))
6878
self.postgresConfiguration = postgresConfiguration
6979
}

Sources/PostgresConnectionPool/PostgresConnectionWrapper.swift

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

9+
/// A wrapper around a postgres connection.
910
public final class PostgresConnectionWrapper {
1011

1112
private let poolConnection: PoolConnection
@@ -35,7 +36,9 @@ public final class PostgresConnectionWrapper {
3536

3637
switch PostgresError.Code(raw: code) {
3738
case .queryCanceled:
38-
throw PoolError.queryCancelled(query: connectionWrapper.poolConnection.query ?? "<unknown>", runtime: connectionWrapper.poolConnection.queryRuntime ?? 0.0)
39+
throw PoolError.queryCancelled(
40+
query: connectionWrapper.poolConnection.query ?? "<unknown>",
41+
runtime: connectionWrapper.poolConnection.queryRuntime ?? 0.0)
3942
default:
4043
throw PoolError.postgresError(error)
4144
}
@@ -54,11 +57,12 @@ public final class PostgresConnectionWrapper {
5457

5558
// MARK: - Public interface, from PostgresConnection
5659

57-
/// A logger to use in case
60+
/// The database logger.
5861
public var logger: Logger {
5962
postgresConnection.logger
6063
}
6164

65+
/// if the connection is closed (which would be an error).
6266
public var isClosed: Bool {
6367
postgresConnection.isClosed
6468
}
@@ -93,14 +97,19 @@ public final class PostgresConnectionWrapper {
9397
postgresConnection.sql(encoder: encoder, decoder: decoder)
9498
}
9599

96-
/// Add a handler for NotificationResponse messages on a certain channel. This is used in conjunction with PostgreSQL's `LISTEN`/`NOTIFY` support: to listen on a channel, you add a listener using this method to handle the NotificationResponse messages, then issue a `LISTEN` query to instruct PostgreSQL to begin sending NotificationResponse messages.
100+
/// Add a handler for NotificationResponse messages on a certain channel.
101+
///
102+
/// This is used in conjunction with PostgreSQL's `LISTEN`/`NOTIFY` support:
103+
/// to listen on a channel, you add a listener using this method to handle the NotificationResponse messages,
104+
/// then issue a `LISTEN` query to instruct PostgreSQL to begin sending NotificationResponse messages.
97105
@discardableResult
98106
public func addListener(
99107
channel: String,
100108
handler notificationHandler: @escaping (PostgresListenContext, PostgresMessage.NotificationResponse) -> Void)
101109
-> PostgresListenContext
102110
{
103-
postgresConnection.addListener(channel: channel, handler: notificationHandler)
111+
poolConnection.query = "LISTEN \(channel)"
112+
return postgresConnection.addListener(channel: channel, handler: notificationHandler)
104113
}
105114

106115
}

0 commit comments

Comments
 (0)