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.
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?