Answer a question

I am creating backend based on Vapor 3.1.10 using Xcode 11.2 and Swift 5.1, database is PostgreSQL 12. I have a question: how to interact with database (CRUD) without POST and GET requests. All tutorials show how to CRUD only based on Request through HTTPS. But what if my app needs to save something in database without interacting with network? Look at my code:

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 {}

classical method to write or read is:

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)
        }
    }
}

How to replace req to another background, safe thread, which I can create locally?

For example:

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

How to replace <#T##DatabaseConnectable#> ?

I will be thankful for any help or advice.

Answers

Based on this question and answers (Is is possible to use Vapor 3 Postgres Fluent in a standalone script?) I realized CRUD like this:

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)
    }

}

It is working, but I am not sure is it good way to do this. Does somebody know?

Logo

PostgreSQL社区为您提供最前沿的新闻资讯和知识内容

更多推荐