SqliteSyncDaos.swift 83 lignes · 2633 octets
import Foundation

struct SqliteSyncOpDao: SyncOpDao {
    let db: SqliteDatabase

    private static let columns = "id, entityType, op, payloadJson, localId, serverId, createdAt, attempts, lastError"

    private static func map(_ row: SqliteRow) -> SyncOpEntity {
        var e = SyncOpEntity(entityType: row.text(1), op: row.text(2))
        e.id = row.int64(0)
        e.payloadJson = row.text(3)
        e.localId = row.int64OrNil(4)
        e.serverId = row.textOrNil(5)
        e.createdAt = row.int64(6)
        e.attempts = row.int(7)
        e.lastError = row.textOrNil(8)
        return e
    }

    @discardableResult
    func insert(_ entity: SyncOpEntity) async throws -> Int64 {
        try await db.insert(
            "INSERT OR REPLACE INTO sync_ops (\(Self.columns)) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
            [
                .rowId(entity.id),
                .text(entity.entityType),
                .text(entity.op),
                .text(entity.payloadJson),
                .optInt(entity.localId),
                .optText(entity.serverId),
                .int(entity.createdAt),
                .int(Int64(entity.attempts)),
                .optText(entity.lastError),
            ]
        )
    }

    func markFailure(id: Int64, error: String?) async throws {
        try await db.write(
            "UPDATE sync_ops SET attempts = attempts + 1, lastError = ? WHERE id = ?",
            [.optText(error), .int(id)]
        )
    }

    func listAll() async throws -> [SyncOpEntity] {
        try await db.query(
            "SELECT \(Self.columns) FROM sync_ops ORDER BY createdAt ASC",
            map: Self.map
        )
    }

    func getById(_ id: Int64) async throws -> SyncOpEntity? {
        try await db.query(
            "SELECT \(Self.columns) FROM sync_ops WHERE id = ?",
            [.int(id)],
            map: Self.map
        ).first
    }

    func deleteById(_ id: Int64) async throws {
        try await db.write("DELETE FROM sync_ops WHERE id = ?", [.int(id)])
    }
}

struct SqliteSyncMetaDao: SyncMetaDao {
    let db: SqliteDatabase

    func upsert(_ entity: SyncMetaEntity) async throws {
        try await db.write(
            "INSERT OR REPLACE INTO sync_meta (\"key\", \"value\") VALUES (?, ?)",
            [.text(entity.key), .text(entity.value)]
        )
    }

    func get(_ key: String) async throws -> SyncMetaEntity? {
        try await db.query(
            "SELECT \"key\", \"value\" FROM sync_meta WHERE \"key\" = ?",
            [.text(key)]
        ) { row in
            SyncMetaEntity(key: row.text(0), value: row.text(1))
        }.first
    }
}