feat(queue): queue as data A2, migration, render and dispatch (#1508)

Filbert approved round 1 (f167b85e). Manifest 782bcb62, 21 files, plus
the QUEUE.md markers and the TOOLS.md section. Lead decision 35.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-09-26 20:14:09 -05:00
co-authored by Claude Opus 5.5
parent c9539baa0f
commit 6ca116b7ba
32 changed files with 4886 additions and 103 deletions
+54 -1
View File
@@ -4,8 +4,10 @@
import assert from "node:assert/strict";
import { spawn, spawnSync } from "node:child_process";
import { readFileSync, readdirSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
import { hostname } from "node:os";
import { join } from "node:path";
import { test } from "node:test";
import { processStart } from "../../discord/src/journal.mjs";
import { cli, genesisCommitted, load, scratchRepo } from "./helpers.mjs";
const HERE = new URL(".", import.meta.url).pathname;
@@ -164,6 +166,22 @@ test("a lock swapped while held is left in place and reported, on a receipt and
unlinkSync(lock);
});
// P1 in withLock: a release that throws after the op becomes a warning on
// the receipt or on the refusal, and names the lock left behind.
test("a lock that cannot be released after an op is reported, on a receipt and on a refusal", async (t) => {
const { repo, m } = await ready(t);
const lock = join(repo.gitDir, "mosaic-queue.lock");
const eacces = () => { throw Object.assign(new Error("denied"), { code: "EACCES" }); };
const io = { ...m.io.realIo, unlink: (p) => (p === lock ? eacces() : m.io.realIo.unlink(p)) };
const done = m.store.mutate(o(repo, { io }), note(9, "x", "note-9-000001"));
assert.match(done.out[0], /^ok note-9-000001 rev 1/);
assert.match(done.err.join("\n"), /warning: cannot release the queue lock \(EACCES\); .*mosaic-queue\.lock may be left in place$/);
unlinkSync(lock);
throwsCode(() => m.store.mutate(o(repo, { io }), note(9, "y", "note-9-000002", "rocko")), 2,
/may note row 9[^]*\nwarning: cannot release the queue lock \(EACCES\); .*mosaic-queue\.lock may be left in place$/);
unlinkSync(lock);
});
test("unlock prints a swapped gate's warning on stderr, the result on stdout", async (t) => {
const { repo, m } = await ready(t);
const gate = join(repo.gitDir, "mosaic-queue.unlock");
@@ -369,5 +387,40 @@ test("an accept-history in progress: an unlocked reader waits on the lock and ne
test("the platform check refuses other filesystems", async (t) => {
const { repo, m } = await ready(t);
const io = { ...m.io.realIo, statfsType: () => 0x6969 };
throwsCode(() => m.store.mutate(o(repo, { io }), note(9, "one", "note-9-000001")), 2, /unsupported filesystem .*type 0x6969/);
throwsCode(() => m.store.mutate(o(repo, { io }), note(9, "one", "note-9-000001")), 2, /unsupported filesystem .*type 0x6969\); ext4, xfs or btrfs only/);
});
test("tmpfs passes only a test layer that allows it (N5)", async (t) => {
const { repo, m } = await ready(t);
assert.equal(m.io.TMPFS, 0x01021994);
assert.equal("allowTmpfs" in m.io.realIo, false);
assert.equal(Object.isFrozen(m.io.realIo), true);
const tmpfs = { ...m.io.realIo, statfsType: () => m.io.TMPFS };
throwsCode(() => m.store.mutate(o(repo, { io: tmpfs }), note(9, "one", "note-9-000001")), 2, /unsupported filesystem .*type 0x1021994\); ext4, xfs or btrfs only/);
throwsCode(() => m.store.unlock(o(repo, { io: tmpfs })), 2, /type 0x1021994/);
throwsCode(() => m.store.mutate(o(repo, { io: { ...tmpfs, allowTmpfs: "yes" } }), note(9, "one", "note-9-000001")), 2, /type 0x1021994/);
const r = m.store.mutate(o(repo, { io: { ...tmpfs, allowTmpfs: true } }), note(9, "one", "note-9-000001"));
assert.match(r.out[0], /^ok note-9-000001 rev 1/);
// allowTmpfs lets tmpfs through, nothing else.
throwsCode(() => m.store.mutate(o(repo, { io: { ...m.io.realIo, statfsType: () => 0x6969, allowTmpfs: true } }), note(9, "two", "note-9-000002")), 2, /type 0x6969/);
});
// P3: unlock returns the result and the warning apart, so a lock record
// written by hand over several lines stays on stdout.
test("unlock keeps a multi-line lock record on stdout (P3)", async (t) => {
const { repo, m } = await ready(t);
const lock = join(repo.gitDir, "mosaic-queue.lock");
const rec = (pid) => ({
pid, start: processStart(process.pid), boot: "00000000-0000-4000-8000-000000000000", host: hostname(), op: "hand-op-0001", verb: "move", at: "2026-09-26T00:00:00.000Z",
});
writeFileSync(lock, JSON.stringify(rec(process.pid), null, 2) + "\n");
const r = m.store.unlock(o(repo));
assert.equal(r.out.length, 1);
assert.match(r.out[0], /^removed queue lock \(mismatch: .*recorded in a previous boot\): \{\n {2}"pid": \d+,\n[^]*"at": "2026-09-26T00:00:00\.000Z"\n\}$/);
assert.deepEqual(r.err, []);
writeFileSync(lock, JSON.stringify(rec(process.pid), null, 2) + "\n");
const c = cli(repo, ["unlock"]);
assert.equal(c.code, 0, c.err);
assert.equal(c.err, "");
assert.match(c.out, /"verb": "move",\n {2}"at"/);
});