Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Docs] add "how to use the package standalone" to readme #560

Open
marc-medley opened this issue Dec 8, 2022 · 3 comments
Open

[Docs] add "how to use the package standalone" to readme #560

marc-medley opened this issue Dec 8, 2022 · 3 comments
Labels
enhancement New feature or request

Comments

@marc-medley
Copy link

As a developer, i would like to use Fluent & FluentSQLiteDriver in both Vapor and non-Vapor applications.

It would be helpful if the documentation approach mentioned by @tanner0101 in Issue vapor/fluent#583 was provided in the vapor/fluent readme.

Going forward, docs.vapor.codes will assume you are using the packages with Vapor. The package readmes will show docs on how to use the package standalone …

@marc-medley marc-medley added the enhancement New feature or request label Dec 8, 2022
@Freelenzer
Copy link

Freelenzer commented Feb 16, 2023

I thin we could just do a PR for this. Would be really helpful. I found the documentation too late.

@0xTim 0xTim transferred this issue from vapor/fluent Apr 13, 2023
@0xTim
Copy link
Member

0xTim commented Apr 13, 2023

Migrating to FluentKit since Fluent is in the docs (as it's the Vapor integration part)

@dioKaratzas
Copy link

dioKaratzas commented Aug 20, 2024

This is how I use it in my projects:

@0xTim is my approach correct?

import NIOCore
import Logging
import NIOPosix
import FluentKit
import NIOConcurrencyHelpers

/// `FluentManager` is responsible for managing Fluent databases, migrations, and related resources.
public final class FluentManager: Sendable {
    private let threadPool: NIOLockedValueBox<NIOThreadPool>
    private let eventLoopGroup: EventLoopGroup
    private let _migrationLogLevel: NIOLockedValueBox<Logger.Level>
    private let logger: Logger

    /// The `Databases` instance that manages the connections to the databases.
    public let databases: Databases

    /// The `Migrations` instance that holds the migration configurations.
    public let migrations: Migrations

    /// The log level used during migration operations.
    public var migrationLogLevel: Logger.Level {
        get { self._migrationLogLevel.withLockedValue { $0 } }
        set { self._migrationLogLevel.withLockedValue { $0 = newValue } }
    }

    /// Initializes a new `FluentManager`.
    ///
    /// - Parameters:
    ///   - threadPool: The thread pool used for background tasks. Defaults to a thread pool with `System.coreCount` threads.
    ///   - eventLoopGroup: The event loop group used for handling event-driven tasks. Defaults to a multi-threaded event loop group with `System.coreCount` threads.
    ///   - migrationLogLevel: The log level to use during migrations. Defaults to `.info`.
    public init(
        threadPool: NIOThreadPool = NIOThreadPool(numberOfThreads: System.coreCount),
        eventLoopGroup: EventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount),
        logger: Logger = Logger(label: "FluentManager"),
        migrationLogLevel: Logger.Level = .info
    ) {
        self.threadPool = NIOLockedValueBox(threadPool)
        self.eventLoopGroup = eventLoopGroup
        self.logger = logger
        self.databases = Databases(threadPool: threadPool, on: eventLoopGroup)
        self.migrations = Migrations()
        self._migrationLogLevel = .init(migrationLogLevel)
        self.threadPool.withLockedValue { $0.start() }
    }

    /// Retrieves a database connection from the `Databases` instance.
    ///
    /// - Parameters:
    ///   - id: The `DatabaseID` used to identify the database connection. Defaults to `nil`, which retrieves the default database.
    ///   - logger: A `Logger` instance used for logging database operations. Defaults to a logger with the label "Fluent".
    /// - Returns: A database connection conforming to `Database`.
    public func db(_ id: DatabaseID? = nil, logger: Logger = .init(label: "Fluent")) -> any Database {
        guard let db = self.databases.database(
            id,
            logger: logger,
            on: self.eventLoopGroup.any()
        ) else {
            fatalError("No database configured for \(id?.string ?? "default")")
        }
        return db
    }

    /// Asynchronously runs forward migrations without confirmation.
    ///
    /// This method sets up the database and then runs any pending migrations.
    ///
    /// - Throws: An error if the migration setup or execution fails.
    public func autoMigrate() async throws {
        let migrator = Migrator(
            databases: self.databases,
            migrations: self.migrations,
            logger: Logger(label: "Fluent.Migrator"),
            on: self.eventLoopGroup.any(),
            migrationLogLevel: self._migrationLogLevel.withLockedValue { $0 }
        )
        try await migrator.setupIfNeeded().flatMap {
            migrator.prepareBatch()
        }.get()
    }

    /// Asynchronously runs reverse migrations without confirmation.
    ///
    /// This method sets up the database and then reverts all applied migrations.
    ///
    /// - Throws: An error if the migration setup or reversion fails.
    public func autoRevert() async throws {
        let migrator = Migrator(
            databases: self.databases,
            migrations: self.migrations,
            logger: Logger(label: "Fluent.Migrator"),
            on: self.eventLoopGroup.any(),
            migrationLogLevel: self._migrationLogLevel.withLockedValue { $0 }
        )
        try await migrator.setupIfNeeded().flatMap {
            migrator.revertAllBatches()
        }.get()
    }

    /// Asynchronously shuts down the `FluentManager`, releasing all resources.
    ///
    /// This method shuts down the databases, thread pool, and event loop group, ensuring a clean termination of all tasks.
    public func shutdown() async {
        await self.databases.shutdownAsync()

        // Shut down the thread pool and event loop group
        self.threadPool.withLockedValue { pool in
            pool.shutdownGracefully { _ in }
        }
        do {
            try await self.eventLoopGroup.shutdownGracefully()
        } catch {
            self.logger.error("Failed to shut down event loop group: \(error.localizedDescription)")
        }
    }

    /// Shuts down the `FluentManager`, releasing all resources.
    ///
    /// This method shuts down the databases, thread pool, and event loop group, ensuring a clean termination of all tasks.
    public func shutdown() {
        self.databases.shutdown()

        // Shut down the thread pool and event loop group
        self.threadPool.withLockedValue { pool in
            pool.shutdownGracefully { _ in }
        }
        do {
            try self.eventLoopGroup.syncShutdownGracefully()
        } catch {
            self.logger.error("Failed to shut down event loop group: \(error.localizedDescription)")
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants