/* Copyright (C) 2026 Kingsrook, LLC. * SPDX-License-Identifier: Apache-2.0 */ import assert from "node:assert/strict"; import { mkdtemp, readdir, readFile, rm } from "node:fs/promises"; import { tmpdir } from "node:os"; import path from "node:path"; import test from "node:test"; import { AttemptJournal, ATTEMPT_LABEL, OWNER_LABEL, cleanAttempt, reapExpired } from "../dist/lifecycle.js"; async function fixture(t) { const directory = await mkdtemp(path.join(tmpdir(), "qqq-journal-test-")); t.after(() => rm(directory, { recursive: true, force: true })); // Windows test host lacks POSIX directory fsync; inject only that operation. // File writes still use fsync. Production's default never skips directory fsync. const journal = new AttemptJournal(directory, async () => undefined); return { directory, journal }; } function identity(attempt) { return { id: "a".repeat(64), name: "/" + attempt.name, labels: { [OWNER_LABEL]: attempt.owner, [ATTEMPT_LABEL]: attempt.id } }; } test("restart recovers a create whose ID response was lost and removes exact owned ID", async t => { const { directory, journal } = await fixture(t); const attempt = await journal.prepare("deployment-a", 1000); const restarted = new AttemptJournal(directory, async () => undefined); const removed = []; const control = { inspect: async name => { assert.equal(name, attempt.name); return identity(attempt); }, remove: async id => removed.push(id), }; assert.deepEqual(await reapExpired(restarted, "deployment-a", control, 61000), { cleaned: 1, failed: 0 }); assert.deepEqual(removed, ["a".repeat(64)]); assert.deepEqual(await readdir(path.join(directory, "active")), []); const events = await Promise.all((await readdir(path.join(directory, "evidence"))).map(async filename => JSON.parse(await readFile(path.join(directory, "evidence", filename), "utf8")))); assert.deepEqual(new Set(events.map(event => event.event)), new Set(["PREPARED", "REMOVAL_REQUESTED", "REMOVED"])); assert.ok(events.every(event => event.id === attempt.id && event.owner === "deployment-a")); }); test("reaper never inspects live or another deployment's leases", async t => { const { journal } = await fixture(t); await journal.prepare("other", 0); await journal.prepare("deployment-a", 60000); const unexpected = async () => { throw new Error("must not inspect/remove"); }; assert.deepEqual(await reapExpired(journal, "deployment-a", { inspect: unexpected, remove: unexpected }, 61000), { cleaned: 0, failed: 0 }); }); test("ownership mismatch never removes a reused name and retains retry evidence", async t => { const { journal } = await fixture(t); const attempt = await journal.prepare("deployment-a", 0); let removals = 0; const control = { inspect: async () => ({ ...identity(attempt), labels: { [OWNER_LABEL]: "another-deployment", [ATTEMPT_LABEL]: attempt.id } }), remove: async () => removals++, }; assert.deepEqual(await reapExpired(journal, "deployment-a", control, 60000), { cleaned: 0, failed: 1 }); assert.equal(removals, 0); assert.equal((await journal.expired("deployment-a", 60000)).length, 1); }); test("failed removal remains retryable after restart, missing container closes lease", async t => { const { directory, journal } = await fixture(t); const attempt = await journal.prepare("deployment-a", 0); await assert.rejects(cleanAttempt(journal, attempt, { inspect: async () => identity(attempt), remove: async () => { throw new Error("daemon disconnected"); }, }), /disconnected/); const restarted = new AttemptJournal(directory, async () => undefined); const result = await reapExpired(restarted, "deployment-a", { inspect: async () => undefined, remove: async () => { throw new Error("must not remove missing container"); }, }, 60000); assert.deepEqual(result, { cleaned: 1, failed: 0 }); assert.deepEqual(await restarted.expired("deployment-a", 60000), []); }); test("durability failure prevents preparation of an active lease", async t => { const { directory } = await fixture(t); const failing = new AttemptJournal(directory, async () => { throw new Error("fsync unsupported"); }); await assert.rejects(failing.prepare("deployment-a"), /fsync unsupported/); assert.deepEqual(await readdir(path.join(directory, "active")), []); });