63 lines
2.9 KiB
TypeScript
63 lines
2.9 KiB
TypeScript
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<void>(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() }
|
|
})
|