无需请求http的Vapor 3 PostgreSQL CRUD 如何使用Application进行数据库查询?在哪里获得Container的后台任务?

我正在使用Xcode 11.2和Swift 5.1基于Vapor 3.1.10创建后端,数据库是PostgreSQL12。我有一个问题:如何在没有POST和GET请求的情况下与数据库(CRUD)进行交互。所有教程都展示了如何仅基于通过HTTPS的请求进行CRUD。但是,如果我的应用需要在不与网络交互的情况下将某些内容保存在数据库中怎么办?看我的代码:

import Vapor
import FluentPostgreSQL

final class Device: PostgreSQLModel {        
    var id: Int?
    var isWorking: Bool
    var serial: Int

    init(isWorking: Bool,serial: Int) {
        self.isWorking = isWorking
        self.serial = serial
    }    
}
extension Device: Content {}
extension Device: Migration {}
extension Device: Parameter {}

写入或读取的经典方法是:

import Vapor

final class DeviceController {        
    func readAll(_ req: Request) throws -> Future<[Device]> {
        return Device.query(on: req).all()
    }

    func create(_ req: Request) throws -> Future<Device> {
        return try req.content.decode(Device.self).flatMap { device in
            return device.save(on: req)
        }
    }
}

如何将req替换为另一个我可以在本地创建的安全线程?

例如:

let device = Device(isWorking: true,serial: 54321)
device.save(on: <#T##DatabaseConnectable#>)

如何替换<#T##DatabaseConnectable#>

感谢您的帮助或建议。

guopu8483 回答:无需请求http的Vapor 3 PostgreSQL CRUD 如何使用Application进行数据库查询?在哪里获得Container的后台任务?

RequestContainer,它有eventLoop,它是DatabaseConnectable

Application,它是Container,它有eventLoop,但不是DatabaseConnectable

如何使用Application进行数据库查询?

在任何Container上,您都可以建立到数据库的池连接,而您可能猜想的连接是DatabaseConnectable

boot.swift中的示例查询

import Vapor
import FluentSQL
import FluentPostgreSQL

public func boot(_ app: Application) throws {
    let _ = app.requestPooledConnection(to: .psql).flatMap { conn in
        return User.query(conn).all().map { users in
            print("just found \(users.count) users")
        }.always {
            try? app.releasePooledConnection(conn,to: .psql)
        }
    }
}

上面的代码将通过.psql容器中的Application标识符请求到PostgreSQL的池化连接,然后对该连接执行查询,然后在always块中将其释放回池。

在哪里获得Container的后台任务?

如果使用https://github.com/vapor/jobshttps://github.com/MihaelIsaev/VaporCron,则在任务声明中将有一个Container对象。

VaporCron的示例

// in boot.swift
import Vapor
import VaporCron

/// Called after your application has initialized.
public func boot(_ app: Application) throws {
    scheduleTasks(on: app)
}

/// Scheduling Cron tasks
private func scheduleTasks(on app: Application) {
    do {
        _ = try VaporCron.schedule(Every1MinCheck.self,on: app)
    } catch {
        print("cron schedule error: \(error)")
    }
}

// in Every1MinCheck.swift
import Vapor
import VaporCron
import FluentSQL
import PostgreSQL

struct Every1MinCheck: VaporCronSchedulable {
    static var expression: String { return "*/1 * * * *" } // every 1 minute

    static func task(on container: VaporCronContainer) -> Future<Void> {
        return container.requestPooledConnection(to: .psql).flatMap { conn in
            return User.query(conn).all().map { users in
                print("just found \(users.count) users")
            }.always {
                try? container.releasePooledConnection(conn,to: .psql)
            }
        }
    }
}
,

基于这个问题和答案(Is is possible to use Vapor 3 Postgres Fluent in a standalone script?),我意识到CRUD就像这样:

import Vapor
import FluentPostgreSQL

final class Device: PostgreSQLModel {
    var id: Int?
    var isWorking: Bool
    var serial: Int

    init(isWorking: Bool,serial: Int) {
        self.isWorking = isWorking
        self.serial = serial
    }
}
extension Device: Content {}
extension Device: Migration {}
extension Device: Parameter {}

final class WorkWithPostgres {

    let databaseConfig = PostgreSQLDatabaseConfig(hostname: "localhost",port: 5432,username: "username",database: "testestest",password: nil)

    let database: PostgreSQLDatabase

    static let shared = WorkWithPostgres()

    private init() {
        database = PostgreSQLDatabase(config: databaseConfig)
    }

    func readAll<T: PostgreSQLModel>(postgreSQLModel: T.Type,completion: (([T]) -> Void)?) {
        let worker = MultiThreadedEventLoopGroup(numberOfThreads: 1)
        let conn = database.newConnection(on: worker)

        let _ = conn.map { connection in
            postgreSQLModel.query(on: connection).all().map { databaseData in
                worker.shutdownGracefully { _ in
                }

                completion?(databaseData)
            }
        }
    }

    func create<T: PostgreSQLModel>(postgreSQLModel: T) {
        let worker = MultiThreadedEventLoopGroup(numberOfThreads: 1)
        let conn = database.newConnection(on: worker)

        let _ = conn.map { connection in
            let _ = postgreSQLModel.save(on: connection).whenComplete {
                worker.shutdownGracefully { _ in
                }
            }
        }
    }

}

final class DeviceController {

    func readAll(completion: (([Device]) -> Void)?) {
        WorkWithPostgres.shared.readAll(postgreSQLModel: Device.self) { devices in
            completion?(devices)
        }
    }

    func create(isWorking: Bool,serial: Int) {
        let device = Device(isWorking: isWorking,serial: serial)

        WorkWithPostgres.shared.create(postgreSQLModel: device)
    }

}

它正在工作,但是我不确定这是个好方法。有人知道吗?

本文链接:https://www.f2er.com/3142168.html

大家都在问