import assert from "node:assert/strict" import { test } from "node:test" import { DatabaseBackgroundWork, databaseBackgroundWork } from "./database-background-work.js" import Fastify from "fastify" import { validatorCompiler, serializerCompiler } from "@fastify/type-provider-zod" import { createBackupsRoutes } from "../routes/backups.js" function deferred() { let resolve!: () => void const promise = new Promise(r => { resolve = r }) return { promise, resolve } } test("drain includes writes scheduled by a task after its HTTP response", async () => { const work = new DatabaseBackgroundWork(), parent = deferred(), child = deferred() work.track(parent.promise.then(() => { work.track(child.promise) })) let finished = false const drain = work.drain().then(() => { finished = true }) parent.resolve(); await parent.promise; await Promise.resolve() assert.equal(finished, false) child.resolve(); await drain; assert.equal(finished, true) }) test("timeout preserves pending tasks for the next attempt", async () => { const work = new DatabaseBackgroundWork(), pending = deferred() work.track(pending.promise) await assert.rejects(work.drain(10), /операция с базой отменена/) let finished = false const retry = work.drain().then(() => { finished = true }) await Promise.resolve(); assert.equal(finished, false) pending.resolve(); await retry; assert.equal(finished, true) }) test("a task rejection is observed without breaking subsequent drain", async () => { const work = new DatabaseBackgroundWork() const task = work.track(Promise.reject(Error("audit failed"))) await assert.rejects(task, /audit failed/) await work.drain() work.track(Promise.resolve()); await work.drain() }) test("real backup HTTP202 keeps its detached job registered through completion", async () => { const pending = deferred(), started = deferred() const app = Fastify(); app.setValidatorCompiler(validatorCompiler); app.setSerializerCompiler(serializerCompiler) await app.register(createBackupsRoutes({ listServers: async () => [{ id: 1 }], appendEvent: async () => undefined as never, create: async () => { started.resolve(); await pending.promise return { id: "drain-backup", serverId: 1, serverName: "router", filename: "test.rsc", sizeBytes: 0, createdAt: "2026-10-07T00:00:00Z", kind: "manual", storage: "local" } }, }), { prefix: "/api" }) try { assert.equal((await app.inject({ method: "POST", url: "/api/backups/create", payload: { serverIds: [1] } })).statusCode, 202) await started.promise let finished = false const drain = databaseBackgroundWork.drain().then(() => { finished = true }) await Promise.resolve(); assert.equal(finished, false) pending.resolve(); await drain; assert.equal(finished, true) } finally { pending.resolve(); await databaseBackgroundWork.drain(); await app.close() } })