Files
f0d695ec97
QRun-IO/ci-policy: ci / fork-guard (push) Skipped
QRun-IO/ci-policy: ci / head-profile (push) Skipped
QRun-IO/ci-policy: ci / application-template-0 (push) Skipped
QRun-IO/ci-policy: ci / gradle-1 (push) Skipped
QRun-IO/ci-policy: ci / java-docker-3 (push) Skipped
QRun-IO/ci-policy: ci / java-docker-4 (push) Skipped
QRun-IO/ci-policy: ci / java-frontend-browser-5 (push) Skipped
QRun-IO/ci-policy: ci / java-maven-6 (push) Skipped
QRun-IO/ci-policy: ci / java-maven-7 (push) Skipped
QRun-IO/ci-policy: ci / node-8 (push) Skipped
QRun-IO/ci-policy: ci / node-9 (push) Skipped
QRun-IO/ci-policy: ci / node-10 (push) Skipped
QRun-IO/ci-policy: ci / node-playwright-11 (push) Skipped
QRun-IO/ci-policy: ci / repository-policy-12 (push) Skipped
QRun-IO/ci-policy: ci / source-config-13 (push) Skipped
QRun-IO/ci-policy: ci / source-config-14 (push) Skipped
QRun-IO/ci-policy: ci / android-0 (push) Skipped
QRun-IO/ci-policy: ci / original-business (push) Skipped
QRun-IO/ci-policy: ci / original-mcp (push) Skipped
QRun-IO/ci-policy: ci / original-voyage (push) Skipped
QRun-IO/ci-policy: ci / original-cli (push) Skipped
QRun-IO/ci-policy: ci / repository-policy (push) Skipped
QRun-IO/ci-policy: ci / java-core-2-head (push) Skipped
QRun-IO/ci-policy: ci / java-docker-3-head (push) Skipped
QRun-IO/ci-policy: ci / java-maven-6-head (push) Skipped
QRun-IO/ci-policy: ci / java-maven-7-head (push) Skipped
QRun-IO/ci-policy: ci / not-enrolled (push) Failing after 7s
QRun-IO/ci-policy: native / fork-deny (push) Skipped
QRun-IO/ci-policy: native / dotnet-0 (push) Skipped
QRun-IO/ci-policy: ci / ci-result (push) Failing after 6s
QRun-IO/ci-policy: native / native-result (push) Successful in 6s
chore: preserve paused QBit work and document remaining issues
Save the current implementation and README, status, and known-issue documentation at the user-requested stop. No completed release or deployment is claimed.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-Authored-By: GPT-6 Codex <noreply@openai.com>
2026-11-04 10:45:28 -06:00

107 lines
4.4 KiB
JavaScript

/* 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")), []);
});