import FluentPostgresDriver import FluentSQLiteDriver import HummingbirdFluent import Logging /// A factory building the `Fluent` service the application persists through. /// /// Built once around the driver the executable picks at startup and called as a function to produce the configured service: `let fluent = service()`. public struct Service: Sendable { // MARK: Properties /// The persistence backend to register. private let driver: Driver /// The logger the database emits through. private let logger: Logger // MARK: Initializers /// Creates a factory for a `Fluent` service backed by the given driver. /// - Parameters: /// - driver: the persistence backend to register. /// - logger: the logger the database emits through. public init( driver: Driver, logger: Logger ) { self.driver = driver self.logger = logger } // MARK: Methods /// Builds a `Fluent` service configured for the driver. /// /// The selected backend is registered as the *default* database, so repositories resolve it with a plain `fluent.db()` and stay agnostic of which /// driver is in use. The returned service is not yet running; add it to the application's service group (`app.addServices(_:)`) so it starts and shuts /// its connection pool down alongside the server. /// - Throws: an error when the TLS context for the PostgreSQL backend cannot be built. /// - Returns: the configured `Fluent` service, ready to be added to the service group. public func callAsFunction() throws -> Fluent { let fluent = Fluent( logger: logger ) switch driver { case .postgres(let configuration): fluent.databases.use( .postgres( configuration: .init( hostname: configuration.host, port: configuration.port, username: configuration.username, password: configuration.password, database: configuration.name, tls: try configuration.tls.postgresTLS() ), maxConnectionsPerEventLoop: configuration.maxConnectionsPerEventLoop ), as: .psql, isDefault: true ) case .inMemory: // A single connection keeps every query pointed at the same in-memory store, rather than each pooled // connection getting its own private database. fluent.databases.use( .sqlite(.memory, maxConnectionsPerEventLoop: 1), as: .sqlite, isDefault: true ) } return fluent } }