feat(cli): S4 follow-up, refusal backoff and tracker boot (row 45, #1527)
Rocko's round 2 candidate, packet agents/rocko/work/s4-follow-up/
(build.patch c8cec070, candidate manifest 5b067a9d, 8/8 OK).
- Definite DM refusals wait the full 30-minute cap, counted from the
journal's last refusal, so five refusals span about two hours before
gave-up (lead decision 73). Unknown outcomes keep doubling.
- Broker close sends at host.mjs:144/150/184/188 pass a callback, which
closes the EPIPE window both reviewers found in round 1.
- README documents manual recovery for an open decision.
- trackers-boot test, X9, X14, and Darkwing's round 1 notes 1-4.
- The append type check stays out; Rocko's reason holds (both reviewers
agree).
Reviews: Darkwing approve (comment 26884), Filbert approve (26886).
Landing gate on b13fef4c plus the patch: every node suite and every
scripts/test-*.sh green, test-task 98/0.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -17,6 +17,15 @@ function journal() {
|
||||
return dir;
|
||||
}
|
||||
|
||||
// A pid that is provably dead: a child spawned and reaped here, then
|
||||
// confirmed gone with kill(pid, 0). A fixed number can belong to a live process.
|
||||
function deadPid() {
|
||||
for (;;) {
|
||||
const { pid } = spawnSync(process.execPath, ["-e", ""], { stdio: "ignore" });
|
||||
if (Number.isSafeInteger(pid) && !pidAlive(pid)) return pid;
|
||||
}
|
||||
}
|
||||
|
||||
function publish(dir, rec) {
|
||||
mkdirSync(lockPath(dir), { recursive: true });
|
||||
writeFileSync(ownerPath(dir), JSON.stringify(rec) + "\n", { mode: 0o600 });
|
||||
@@ -76,7 +85,7 @@ test("lock: the claim is exclusive; a second start against a live owner refuses"
|
||||
|
||||
test("lock: a stale lock (dead owner, reused pid, or record without start) refuses run and is never signaled; only unlock clears it", () => {
|
||||
const dir = journal();
|
||||
const dead = { pid: 2 ** 22 - 7, start: "1", boot: bootId() };
|
||||
const dead = { pid: deadPid(), start: "1", boot: bootId() };
|
||||
publish(dir, dead);
|
||||
assert.equal(stopTarget(dir), null);
|
||||
assert.throws(() => writePid(dir, process.pid), (err) => err instanceof DiscordError && /which is gone/.test(err.message) && /unlock/.test(err.message));
|
||||
@@ -116,7 +125,7 @@ test("lock: a stale lock (dead owner, reused pid, or record without start) refus
|
||||
assert.throws(() => unlock(dir), /cannot be verified; nothing removed/);
|
||||
rmSync(stopPath(dir));
|
||||
rmSync(lockPath(dir), { recursive: true });
|
||||
publish(dir, { pid: 2 ** 22 - 7, start: "1" });
|
||||
publish(dir, { pid: deadPid(), start: "1" });
|
||||
assert.equal(ownerState(readPid(dir)), "dead");
|
||||
unlock(dir);
|
||||
rmSync(stopPath(dir));
|
||||
@@ -227,8 +236,9 @@ test("lock: identity syntax; only canonical unsigned decimal start ticks and low
|
||||
|
||||
test("lock: a process whose start marker or boot id cannot be read refuses to claim", () => {
|
||||
const dir = journal();
|
||||
assert.equal(processStart(2 ** 22 - 7), null);
|
||||
assert.throws(() => writePid(dir, 2 ** 22 - 7), (err) => err instanceof DiscordError && /start time or the boot id/.test(err.message));
|
||||
const gone = deadPid();
|
||||
assert.equal(processStart(gone), null);
|
||||
assert.throws(() => writePid(dir, gone), (err) => err instanceof DiscordError && /start time or the boot id/.test(err.message));
|
||||
assert.equal(existsSync(lockPath(dir)), false, "nothing was left behind");
|
||||
const noBoot = (pid) => ({ start: processStart(pid), boot: null });
|
||||
assert.throws(() => writePid(dir, process.pid, { identity: noBoot }), /start time or the boot id/);
|
||||
@@ -276,7 +286,7 @@ test("lock: four processes racing for the same binding; exactly one claims it an
|
||||
|
||||
test("lock: stale handoff; concurrent starts over a stale lock all refuse, nothing reclaims, one unlock then exactly one live owner", async () => {
|
||||
const dir = journal();
|
||||
const stale = { pid: 2 ** 22 - 7, start: "1", boot: bootId() };
|
||||
const stale = { pid: deadPid(), start: "1", boot: bootId() };
|
||||
publish(dir, stale);
|
||||
// Several starts race over the stale lock: none may reclaim it.
|
||||
const r1 = await race(dir, 4, "stale");
|
||||
@@ -315,7 +325,7 @@ test("lock: four-party schedule; claims landing inside an unlock's gap never sur
|
||||
const worker = fileURLToPath(new URL("../fixtures/claim-worker.mjs", import.meta.url));
|
||||
const go = join(dir, "go");
|
||||
writeFileSync(go, "");
|
||||
const stale = { pid: 2 ** 22 - 7, start: "1", boot: bootId() };
|
||||
const stale = { pid: deadPid(), start: "1", boot: bootId() };
|
||||
publish(dir, stale);
|
||||
const claims = [];
|
||||
const claim = (tag) => {
|
||||
|
||||
Reference in New Issue
Block a user