Vapor 3 PostgreSQL CRUD без запросов http - PullRequest
1 голос
/ 07 ноября 2019

Я создаю бэкэнд на основе Vapor 3.1.10 с использованием Xcode 11.2 и Swift 5.1, база данных - PostgreSQL 12. У меня вопрос: как взаимодействовать с базой данных (CRUD) без запросов POST и GET. Все учебники показывают, как CRUD только на основе запроса через HTTPS. Но что, если моему приложению нужно что-то сохранить в базе данных, не взаимодействуя с сетью? Посмотрите на мой код:

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

Буду благодарен за любую помощь или совет.

1 Ответ

1 голос
/ 08 ноября 2019

Request равно Container, имеет 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)
        }
    }
}

Приведенный выше код будет запрашивать пул соединения с PostgreSQL через идентификатор .psql из контейнера Application, затем выполнить запрос для этого соединения, затемв always заблокируйте его, чтобы освободить это соединение обратно в пул.

Где взять Container для фоновой задачи?

Если вы используете https://github.com/vapor/jobs или https://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)
            }
        }
    }
}
...