From d889fe8d0761f02596c9cd789aa7816d4f2d82fa Mon Sep 17 00:00:00 2001 From: Gwynne Raskind Date: Mon, 25 Aug 2025 11:54:43 -0500 Subject: [PATCH 1/2] Add passthrough configuration parameters for the new idle connection pruning support in AsyncKit 1.21.0, enabling direct use by Fluent users. --- .github/workflows/test.yml | 12 +++-- Package.swift | 7 ++- .../vapor-fluentpostgresdriver-logo.svg | 30 ++++++------ .../FluentPostgresConfiguration.swift | 46 +++++++++++++++++-- .../FluentPostgresDatabase.swift | 2 +- .../PostgresConverterDelegate.swift | 2 +- .../FluentPostgresDriverTests.swift | 3 ++ 7 files changed, 77 insertions(+), 25 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 15b15bb..cd903c4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,7 +29,7 @@ jobs: container: swift:noble steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: { 'fetch-depth': 0 } - name: API breaking changes run: | @@ -74,10 +74,12 @@ jobs: POSTGRES_HOST_AUTH_METHOD: ${{ matrix.postgres-auth }} POSTGRES_INITDB_ARGS: --auth-host=${{ matrix.postgres-auth }} steps: + - name: Ensure curl is available + run: apt-get update -y && apt-get install -y curl - name: Check out package - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Run all tests - run: swift test --sanitize=thread --enable-code-coverage + run: swift test --enable-code-coverage - name: Submit coverage report to Codecov.io uses: vapor/swift-codecov-action@v0.3 with: @@ -115,6 +117,6 @@ jobs: PGPASSWORD="${POSTGRES_PASSWORD_A}" psql -w "${POSTGRES_DB_B}" <<<"ALTER SCHEMA public OWNER TO ${POSTGRES_USER_B};" timeout-minutes: 15 - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Run all tests - run: swift test --sanitize=thread + run: swift test diff --git a/Package.swift b/Package.swift index 8035350..0ea5ef3 100644 --- a/Package.swift +++ b/Package.swift @@ -13,8 +13,9 @@ let package = Package( .library(name: "FluentPostgresDriver", targets: ["FluentPostgresDriver"]), ], dependencies: [ - .package(url: "https://github.com/vapor/fluent-kit.git", from: "1.49.0"), - .package(url: "https://github.com/vapor/postgres-kit.git", from: "2.13.4"), + .package(url: "https://github.com/vapor/fluent-kit.git", from: "1.52.2"), + .package(url: "https://github.com/vapor/postgres-kit.git", from: "2.14.0"), + .package(url: "https://github.com/vapor/async-kit.git", from: "1.21.0"), ], targets: [ .target( @@ -23,6 +24,7 @@ let package = Package( .product(name: "FluentKit", package: "fluent-kit"), .product(name: "FluentSQL", package: "fluent-kit"), .product(name: "PostgresKit", package: "postgres-kit"), + .product(name: "AsyncKit", package: "async-kit"), ], swiftSettings: swiftSettings ), @@ -39,6 +41,7 @@ let package = Package( var swiftSettings: [SwiftSetting] { [ .enableUpcomingFeature("ExistentialAny"), + .enableUpcomingFeature("MemberImportVisibility"), .enableUpcomingFeature("ConciseMagicFile"), .enableUpcomingFeature("ForwardTrailingClosures"), .enableUpcomingFeature("DisableOutwardActorInference"), diff --git a/Sources/FluentPostgresDriver/Docs.docc/Resources/vapor-fluentpostgresdriver-logo.svg b/Sources/FluentPostgresDriver/Docs.docc/Resources/vapor-fluentpostgresdriver-logo.svg index 4cc9947..79211b7 100644 --- a/Sources/FluentPostgresDriver/Docs.docc/Resources/vapor-fluentpostgresdriver-logo.svg +++ b/Sources/FluentPostgresDriver/Docs.docc/Resources/vapor-fluentpostgresdriver-logo.svg @@ -1,21 +1,25 @@ - - - + + + - - - + + + - - - + + + - - + + diff --git a/Sources/FluentPostgresDriver/FluentPostgresConfiguration.swift b/Sources/FluentPostgresDriver/FluentPostgresConfiguration.swift index 4055646..8700054 100644 --- a/Sources/FluentPostgresDriver/FluentPostgresConfiguration.swift +++ b/Sources/FluentPostgresDriver/FluentPostgresConfiguration.swift @@ -15,6 +15,10 @@ extension DatabaseConfigurationFactory { /// - urlString: The URL describing the connection, as a string. /// - maxConnectionsPerEventLoop: Maximum number of connections to open per event loop. /// - connectionPoolTimeout: Maximum time to wait for a connection to become available per request. + /// - pruneInterval: How often to check for and prune idle database connections. If `nil` (the default), + /// no pruning is performed. + /// - maxIdleTimeBeforePruning: How long a connection may remain idle before being pruned, if pruning is enabled. + /// Defaults to 2 minutes. Ignored if `pruneInterval` is `nil`. /// - encodingContext: Encoding context to use for serializing data. /// - decodingContext: Decoding context to use for deserializing data. /// - sqlLogLevel: Level at which to log SQL queries. @@ -22,6 +26,8 @@ extension DatabaseConfigurationFactory { url urlString: String, maxConnectionsPerEventLoop: Int = 1, connectionPoolTimeout: TimeAmount = .seconds(10), + pruneInterval: TimeAmount? = nil, + maxIdleTimeBeforePruning: TimeAmount = .seconds(120), encodingContext: PostgresEncodingContext = .default, decodingContext: PostgresDecodingContext = .default, sqlLogLevel: Logger.Level = .debug @@ -30,6 +36,8 @@ extension DatabaseConfigurationFactory { configuration: try .init(url: urlString), maxConnectionsPerEventLoop: maxConnectionsPerEventLoop, connectionPoolTimeout: connectionPoolTimeout, + pruneInterval: pruneInterval, + maxIdleTimeBeforePruning: maxIdleTimeBeforePruning, encodingContext: encodingContext, decodingContext: decodingContext, sqlLogLevel: sqlLogLevel @@ -44,6 +52,10 @@ extension DatabaseConfigurationFactory { /// - url: The URL describing the connection. /// - maxConnectionsPerEventLoop: Maximum number of connections to open per event loop. /// - connectionPoolTimeout: Maximum time to wait for a connection to become available per request. + /// - pruneInterval: How often to check for and prune idle database connections. If `nil` (the default), + /// no pruning is performed. + /// - maxIdleTimeBeforePruning: How long a connection may remain idle before being pruned, if pruning is enabled. + /// Defaults to 2 minutes. Ignored if `pruneInterval` is `nil`. /// - encodingContext: Encoding context to use for serializing data. /// - decodingContext: Decoding context to use for deserializing data. /// - sqlLogLevel: Level at which to log SQL queries. @@ -51,6 +63,8 @@ extension DatabaseConfigurationFactory { url: URL, maxConnectionsPerEventLoop: Int = 1, connectionPoolTimeout: TimeAmount = .seconds(10), + pruneInterval: TimeAmount? = nil, + maxIdleTimeBeforePruning: TimeAmount = .seconds(120), encodingContext: PostgresEncodingContext = .default, decodingContext: PostgresDecodingContext = .default, sqlLogLevel: Logger.Level = .debug @@ -59,6 +73,8 @@ extension DatabaseConfigurationFactory { configuration: try .init(url: url), maxConnectionsPerEventLoop: maxConnectionsPerEventLoop, connectionPoolTimeout: connectionPoolTimeout, + pruneInterval: pruneInterval, + maxIdleTimeBeforePruning: maxIdleTimeBeforePruning, encodingContext: encodingContext, decodingContext: decodingContext, sqlLogLevel: sqlLogLevel @@ -71,6 +87,10 @@ extension DatabaseConfigurationFactory { /// - configuration: A ``PostgresKit/SQLPostgresConfiguration`` describing the connection. /// - maxConnectionsPerEventLoop: Maximum number of connections to open per event loop. /// - connectionPoolTimeout: Maximum time to wait for a connection to become available per request. + /// - pruneInterval: How often to check for and prune idle database connections. If `nil` (the default), + /// no pruning is performed. + /// - maxIdleTimeBeforePruning: How long a connection may remain idle before being pruned, if pruning is enabled. + /// Defaults to 2 minutes. Ignored if `pruneInterval` is `nil`. /// - encodingContext: Encoding context to use for serializing data. /// - decodingContext: Decoding context to use for deserializing data. /// - sqlLogLevel: Level at which to log SQL queries. @@ -78,6 +98,8 @@ extension DatabaseConfigurationFactory { configuration: SQLPostgresConfiguration, maxConnectionsPerEventLoop: Int = 1, connectionPoolTimeout: TimeAmount = .seconds(10), + pruneInterval: TimeAmount? = nil, + maxIdleTimeBeforePruning: TimeAmount = .seconds(120), encodingContext: PostgresEncodingContext, decodingContext: PostgresDecodingContext, sqlLogLevel: Logger.Level = .debug @@ -87,6 +109,8 @@ extension DatabaseConfigurationFactory { configuration: configuration, maxConnectionsPerEventLoop: maxConnectionsPerEventLoop, connectionPoolTimeout: connectionPoolTimeout, + pruningInterval: pruneInterval, + maxIdleTimeBeforePruning: maxIdleTimeBeforePruning, encodingContext: encodingContext, decodingContext: decodingContext, sqlLogLevel: sqlLogLevel @@ -108,12 +132,14 @@ extension DatabaseConfigurationFactory { /// /// _ = DatabaseConfigurationFactory.postgres(configuration: .init(unixDomainSocketPath: "", username: "")) extension DatabaseConfigurationFactory { - /// ``postgres(configuration:maxConnectionsPerEventLoop:connectionPoolTimeout:encodingContext:decodingContext:sqlLogLevel:)`` + /// ``postgres(configuration:maxConnectionsPerEventLoop:connectionPoolTimeout:pruneInterval:maxIdleTimeBeforePruning:encodingContext:decodingContext:sqlLogLevel:)`` /// with the `decodingContext` defaulted. public static func postgres( configuration: SQLPostgresConfiguration, maxConnectionsPerEventLoop: Int = 1, connectionPoolTimeout: TimeAmount = .seconds(10), + pruneInterval: TimeAmount? = nil, + maxIdleTimeBeforePruning: TimeAmount = .seconds(120), encodingContext: PostgresEncodingContext, sqlLogLevel: Logger.Level = .debug ) -> DatabaseConfigurationFactory { @@ -121,18 +147,22 @@ extension DatabaseConfigurationFactory { configuration: configuration, maxConnectionsPerEventLoop: maxConnectionsPerEventLoop, connectionPoolTimeout: connectionPoolTimeout, + pruneInterval: pruneInterval, + maxIdleTimeBeforePruning: maxIdleTimeBeforePruning, encodingContext: encodingContext, decodingContext: .default, sqlLogLevel: sqlLogLevel ) } - /// ``postgres(configuration:maxConnectionsPerEventLoop:connectionPoolTimeout:encodingContext:decodingContext:sqlLogLevel:)`` + /// ``postgres(configuration:maxConnectionsPerEventLoop:connectionPoolTimeout:pruneInterval:maxIdleTimeBeforePruning:encodingContext:decodingContext:sqlLogLevel:)`` /// with the `encodingContext` defaulted. public static func postgres( configuration: SQLPostgresConfiguration, maxConnectionsPerEventLoop: Int = 1, connectionPoolTimeout: TimeAmount = .seconds(10), + pruneInterval: TimeAmount? = nil, + maxIdleTimeBeforePruning: TimeAmount = .seconds(120), decodingContext: PostgresDecodingContext, sqlLogLevel: Logger.Level = .debug ) -> DatabaseConfigurationFactory { @@ -140,24 +170,30 @@ extension DatabaseConfigurationFactory { configuration: configuration, maxConnectionsPerEventLoop: maxConnectionsPerEventLoop, connectionPoolTimeout: connectionPoolTimeout, + pruneInterval: pruneInterval, + maxIdleTimeBeforePruning: maxIdleTimeBeforePruning, encodingContext: .default, decodingContext: decodingContext, sqlLogLevel: sqlLogLevel ) } - /// ``postgres(configuration:maxConnectionsPerEventLoop:connectionPoolTimeout:encodingContext:decodingContext:sqlLogLevel:)`` + /// ``postgres(configuration:maxConnectionsPerEventLoop:connectionPoolTimeout:pruneInterval:maxIdleTimeBeforePruning:encodingContext:decodingContext:sqlLogLevel:)`` /// with both `encodingContext` and `decodingContext` defaulted. public static func postgres( configuration: SQLPostgresConfiguration, maxConnectionsPerEventLoop: Int = 1, connectionPoolTimeout: TimeAmount = .seconds(10), + pruneInterval: TimeAmount? = nil, + maxIdleTimeBeforePruning: TimeAmount = .seconds(120), sqlLogLevel: Logger.Level = .debug ) -> DatabaseConfigurationFactory { .postgres( configuration: configuration, maxConnectionsPerEventLoop: maxConnectionsPerEventLoop, connectionPoolTimeout: connectionPoolTimeout, + pruneInterval: pruneInterval, + maxIdleTimeBeforePruning: maxIdleTimeBeforePruning, encodingContext: .default, decodingContext: .default, sqlLogLevel: sqlLogLevel @@ -171,6 +207,8 @@ struct FluentPostgresConfiguration let decodingContext: PostgresDecodingContext let sqlLogLevel: Logger.Level @@ -181,6 +219,8 @@ struct FluentPostgresConfiguration(_ closure: @escaping @Sendable (any Database) -> EventLoopFuture) -> EventLoopFuture { + func transaction(_ closure: @escaping @Sendable (any Database) -> EventLoopFuture) -> EventLoopFuture { guard !self.inTransaction else { return closure(self) } diff --git a/Sources/FluentPostgresDriver/PostgresConverterDelegate.swift b/Sources/FluentPostgresDriver/PostgresConverterDelegate.swift index 63e91bd..ed525dd 100644 --- a/Sources/FluentPostgresDriver/PostgresConverterDelegate.swift +++ b/Sources/FluentPostgresDriver/PostgresConverterDelegate.swift @@ -20,7 +20,7 @@ struct PostgresConverterDelegate: SQLConverterDelegate { case .dictionary: SQLRaw("JSONB") case .array(of: let type): - if let type = type, let dataType = self.customDataType(type) { + if let type, let dataType = self.customDataType(type) { SQLArrayDataType(dataType: dataType) } else { SQLRaw("JSONB") diff --git a/Tests/FluentPostgresDriverTests/FluentPostgresDriverTests.swift b/Tests/FluentPostgresDriverTests/FluentPostgresDriverTests.swift index c268085..8ae49f6 100644 --- a/Tests/FluentPostgresDriverTests/FluentPostgresDriverTests.swift +++ b/Tests/FluentPostgresDriverTests/FluentPostgresDriverTests.swift @@ -1,6 +1,7 @@ import FluentBenchmark import FluentKit import FluentPostgresDriver +import FluentSQL import Logging import PostgresKit import SQLKit @@ -310,6 +311,8 @@ extension DatabaseConfigurationFactory { return .postgres( configuration: baseSubconfig, connectionPoolTimeout: .seconds(30), + pruneInterval: .seconds(30), + maxIdleTimeBeforePruning: .seconds(60), encodingContext: encodingContext, decodingContext: decodingContext ) From dc0d053a588d1ea92953c768de2c46e5e51449ee Mon Sep 17 00:00:00 2001 From: Gwynne Raskind Date: Tue, 26 Aug 2025 09:17:54 -0500 Subject: [PATCH 2/2] Silence API breakage complaints by doing it the even uglier way --- .../FluentPostgresConfiguration.swift | 175 ++++++++++++++++-- .../FluentPostgresDriverTests.swift | 2 +- 2 files changed, 164 insertions(+), 13 deletions(-) diff --git a/Sources/FluentPostgresDriver/FluentPostgresConfiguration.swift b/Sources/FluentPostgresDriver/FluentPostgresConfiguration.swift index 8700054..56ca567 100644 --- a/Sources/FluentPostgresDriver/FluentPostgresConfiguration.swift +++ b/Sources/FluentPostgresDriver/FluentPostgresConfiguration.swift @@ -6,6 +6,157 @@ import NIOCore import PostgresKit import PostgresNIO +extension DatabaseConfigurationFactory { + /// Create a PostgreSQL database configuration from a URL string. + /// + /// See ``PostgresKit/SQLPostgresConfiguration/init(url:)`` for the allowed URL format. + /// + /// - Parameters: + /// - urlString: The URL describing the connection, as a string. + /// - maxConnectionsPerEventLoop: Maximum number of connections to open per event loop. + /// - connectionPoolTimeout: Maximum time to wait for a connection to become available per request. + /// - encodingContext: Encoding context to use for serializing data. + /// - decodingContext: Decoding context to use for deserializing data. + /// - sqlLogLevel: Level at which to log SQL queries. + public static func postgres( + url urlString: String, + maxConnectionsPerEventLoop: Int = 1, + connectionPoolTimeout: TimeAmount = .seconds(10), + encodingContext: PostgresEncodingContext = .default, + decodingContext: PostgresDecodingContext = .default, + sqlLogLevel: Logger.Level = .debug + ) throws -> Self { + .postgres( + configuration: try .init(url: urlString), + maxConnectionsPerEventLoop: maxConnectionsPerEventLoop, + connectionPoolTimeout: connectionPoolTimeout, + pruneInterval: nil, + encodingContext: encodingContext, + decodingContext: decodingContext, + sqlLogLevel: sqlLogLevel + ) + } + + /// Create a PostgreSQL database configuration from a URL. + /// + /// See ``PostgresKit/SQLPostgresConfiguration/init(url:)`` for the allowed URL format. + /// + /// - Parameters: + /// - url: The URL describing the connection. + /// - maxConnectionsPerEventLoop: Maximum number of connections to open per event loop. + /// - connectionPoolTimeout: Maximum time to wait for a connection to become available per request. + /// - encodingContext: Encoding context to use for serializing data. + /// - decodingContext: Decoding context to use for deserializing data. + /// - sqlLogLevel: Level at which to log SQL queries. + public static func postgres( + url: URL, + maxConnectionsPerEventLoop: Int = 1, + connectionPoolTimeout: TimeAmount = .seconds(10), + encodingContext: PostgresEncodingContext = .default, + decodingContext: PostgresDecodingContext = .default, + sqlLogLevel: Logger.Level = .debug + ) throws -> Self { + .postgres( + configuration: try .init(url: url), + maxConnectionsPerEventLoop: maxConnectionsPerEventLoop, + connectionPoolTimeout: connectionPoolTimeout, + pruneInterval: nil, + encodingContext: encodingContext, + decodingContext: decodingContext, + sqlLogLevel: sqlLogLevel + ) + } + + /// Create a PostgreSQL database configuration from lower-level configuration. + /// + /// - Parameters: + /// - configuration: A ``PostgresKit/SQLPostgresConfiguration`` describing the connection. + /// - maxConnectionsPerEventLoop: Maximum number of connections to open per event loop. + /// - connectionPoolTimeout: Maximum time to wait for a connection to become available per request. + /// - encodingContext: Encoding context to use for serializing data. + /// - decodingContext: Decoding context to use for deserializing data. + /// - sqlLogLevel: Level at which to log SQL queries. + public static func postgres( + configuration: SQLPostgresConfiguration, + maxConnectionsPerEventLoop: Int = 1, + connectionPoolTimeout: TimeAmount = .seconds(10), + encodingContext: PostgresEncodingContext, + decodingContext: PostgresDecodingContext, + sqlLogLevel: Logger.Level = .debug + ) -> Self { + .postgres( + configuration: configuration, + maxConnectionsPerEventLoop: maxConnectionsPerEventLoop, + connectionPoolTimeout: connectionPoolTimeout, + pruneInterval: nil, + encodingContext: encodingContext, + decodingContext: decodingContext, + sqlLogLevel: sqlLogLevel + ) + } +} + +extension DatabaseConfigurationFactory { + /// ``postgres(configuration:maxConnectionsPerEventLoop:connectionPoolTimeout:encodingContext:decodingContext:sqlLogLevel:)`` + /// with the `decodingContext` defaulted. + public static func postgres( + configuration: SQLPostgresConfiguration, + maxConnectionsPerEventLoop: Int = 1, + connectionPoolTimeout: TimeAmount = .seconds(10), + encodingContext: PostgresEncodingContext, + sqlLogLevel: Logger.Level = .debug + ) -> Self { + .postgres( + configuration: configuration, + maxConnectionsPerEventLoop: maxConnectionsPerEventLoop, + connectionPoolTimeout: connectionPoolTimeout, + pruneInterval: nil, + encodingContext: encodingContext, + decodingContext: .default, + sqlLogLevel: sqlLogLevel + ) + } + + /// ``postgres(configuration:maxConnectionsPerEventLoop:connectionPoolTimeout:encodingContext:decodingContext:sqlLogLevel:)`` + /// with the `encodingContext` defaulted. + public static func postgres( + configuration: SQLPostgresConfiguration, + maxConnectionsPerEventLoop: Int = 1, + connectionPoolTimeout: TimeAmount = .seconds(10), + decodingContext: PostgresDecodingContext, + sqlLogLevel: Logger.Level = .debug + ) -> Self { + .postgres( + configuration: configuration, + maxConnectionsPerEventLoop: maxConnectionsPerEventLoop, + connectionPoolTimeout: connectionPoolTimeout, + pruneInterval: nil, + encodingContext: .default, + decodingContext: decodingContext, + sqlLogLevel: sqlLogLevel + ) + } + + /// ``postgres(configuration:maxConnectionsPerEventLoop:connectionPoolTimeout:encodingContext:decodingContext:sqlLogLevel:)`` + /// with both `encodingContext` and `decodingContext` defaulted. + public static func postgres( + configuration: SQLPostgresConfiguration, + maxConnectionsPerEventLoop: Int = 1, + connectionPoolTimeout: TimeAmount = .seconds(10), + sqlLogLevel: Logger.Level = .debug + ) -> Self { + .postgres( + configuration: configuration, + maxConnectionsPerEventLoop: maxConnectionsPerEventLoop, + connectionPoolTimeout: connectionPoolTimeout, + pruneInterval: nil, + encodingContext: .default, + decodingContext: .default, + sqlLogLevel: sqlLogLevel + ) + } +} + extension DatabaseConfigurationFactory { /// Create a PostgreSQL database configuration from a URL string. /// @@ -26,12 +177,12 @@ extension DatabaseConfigurationFactory { url urlString: String, maxConnectionsPerEventLoop: Int = 1, connectionPoolTimeout: TimeAmount = .seconds(10), - pruneInterval: TimeAmount? = nil, + pruneInterval: TimeAmount?, maxIdleTimeBeforePruning: TimeAmount = .seconds(120), encodingContext: PostgresEncodingContext = .default, decodingContext: PostgresDecodingContext = .default, sqlLogLevel: Logger.Level = .debug - ) throws -> DatabaseConfigurationFactory { + ) throws -> Self { .postgres( configuration: try .init(url: urlString), maxConnectionsPerEventLoop: maxConnectionsPerEventLoop, @@ -63,12 +214,12 @@ extension DatabaseConfigurationFactory { url: URL, maxConnectionsPerEventLoop: Int = 1, connectionPoolTimeout: TimeAmount = .seconds(10), - pruneInterval: TimeAmount? = nil, + pruneInterval: TimeAmount?, maxIdleTimeBeforePruning: TimeAmount = .seconds(120), encodingContext: PostgresEncodingContext = .default, decodingContext: PostgresDecodingContext = .default, sqlLogLevel: Logger.Level = .debug - ) throws -> DatabaseConfigurationFactory { + ) throws -> Self { .postgres( configuration: try .init(url: url), maxConnectionsPerEventLoop: maxConnectionsPerEventLoop, @@ -98,12 +249,12 @@ extension DatabaseConfigurationFactory { configuration: SQLPostgresConfiguration, maxConnectionsPerEventLoop: Int = 1, connectionPoolTimeout: TimeAmount = .seconds(10), - pruneInterval: TimeAmount? = nil, + pruneInterval: TimeAmount?, maxIdleTimeBeforePruning: TimeAmount = .seconds(120), encodingContext: PostgresEncodingContext, decodingContext: PostgresDecodingContext, sqlLogLevel: Logger.Level = .debug - ) -> DatabaseConfigurationFactory { + ) -> Self { .init { FluentPostgresConfiguration( configuration: configuration, @@ -138,11 +289,11 @@ extension DatabaseConfigurationFactory { configuration: SQLPostgresConfiguration, maxConnectionsPerEventLoop: Int = 1, connectionPoolTimeout: TimeAmount = .seconds(10), - pruneInterval: TimeAmount? = nil, + pruneInterval: TimeAmount?, maxIdleTimeBeforePruning: TimeAmount = .seconds(120), encodingContext: PostgresEncodingContext, sqlLogLevel: Logger.Level = .debug - ) -> DatabaseConfigurationFactory { + ) -> Self { .postgres( configuration: configuration, maxConnectionsPerEventLoop: maxConnectionsPerEventLoop, @@ -161,11 +312,11 @@ extension DatabaseConfigurationFactory { configuration: SQLPostgresConfiguration, maxConnectionsPerEventLoop: Int = 1, connectionPoolTimeout: TimeAmount = .seconds(10), - pruneInterval: TimeAmount? = nil, + pruneInterval: TimeAmount?, maxIdleTimeBeforePruning: TimeAmount = .seconds(120), decodingContext: PostgresDecodingContext, sqlLogLevel: Logger.Level = .debug - ) -> DatabaseConfigurationFactory { + ) -> Self { .postgres( configuration: configuration, maxConnectionsPerEventLoop: maxConnectionsPerEventLoop, @@ -184,10 +335,10 @@ extension DatabaseConfigurationFactory { configuration: SQLPostgresConfiguration, maxConnectionsPerEventLoop: Int = 1, connectionPoolTimeout: TimeAmount = .seconds(10), - pruneInterval: TimeAmount? = nil, + pruneInterval: TimeAmount?, maxIdleTimeBeforePruning: TimeAmount = .seconds(120), sqlLogLevel: Logger.Level = .debug - ) -> DatabaseConfigurationFactory { + ) -> Self { .postgres( configuration: configuration, maxConnectionsPerEventLoop: maxConnectionsPerEventLoop, diff --git a/Tests/FluentPostgresDriverTests/FluentPostgresDriverTests.swift b/Tests/FluentPostgresDriverTests/FluentPostgresDriverTests.swift index 8ae49f6..a45ebc7 100644 --- a/Tests/FluentPostgresDriverTests/FluentPostgresDriverTests.swift +++ b/Tests/FluentPostgresDriverTests/FluentPostgresDriverTests.swift @@ -298,7 +298,7 @@ extension DatabaseConfigurationFactory { subconfig: String, encodingContext: PostgresEncodingContext = .default, decodingContext: PostgresDecodingContext = .default - ) -> DatabaseConfigurationFactory { + ) -> Self { let baseSubconfig = SQLPostgresConfiguration( hostname: env("POSTGRES_HOSTNAME_\(subconfig)") ?? "localhost", port: env("POSTGRES_PORT_\(subconfig)").flatMap(Int.init) ?? SQLPostgresConfiguration.ianaPortNumber,