Files
MikrotikManager/backend/src/services/database-background-work.test.ts
T

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() }
})