perf(web): deduplicate control plane gate state
This commit is contained in:
@@ -2,6 +2,7 @@ import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { recordFailure } from "./wbv2-failure-ledger.mjs";
|
||||
|
||||
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const abs = (file) => path.join(root, file);
|
||||
@@ -64,6 +65,7 @@ const releaseLock = () => {
|
||||
let stopRequested = false;
|
||||
let stopSignal;
|
||||
let iteration = 0;
|
||||
let terminalCompleted = false;
|
||||
let fatalHandled = false;
|
||||
const stopFromSignal = (signal) => {
|
||||
stopRequested = true;
|
||||
@@ -97,8 +99,15 @@ function appendLog(text) {
|
||||
fs.appendFileSync(abs(supervisorLog), `[${new Date().toISOString()}] ${text}\n`);
|
||||
}
|
||||
function writeCheckpoint(payload) {
|
||||
const next = { schemaVersion: 1, pid: process.pid, updatedAt: new Date().toISOString(), ...payload };
|
||||
const stable = (value) => { const { pid, updatedAt, ...rest } = value ?? {}; return rest; };
|
||||
try {
|
||||
const current = JSON.parse(fs.readFileSync(abs(checkpointPath), "utf8"));
|
||||
if (JSON.stringify(stable(current)) === JSON.stringify(stable(next))) return;
|
||||
}
|
||||
catch { /* The first checkpoint or an interrupted write is not reusable. */ }
|
||||
const temporaryPath = `${checkpointPath}.tmp-${process.pid}`;
|
||||
fs.writeFileSync(abs(temporaryPath), `${JSON.stringify({ schemaVersion: 1, pid: process.pid, updatedAt: new Date().toISOString(), ...payload }, null, 2)}\n`);
|
||||
fs.writeFileSync(abs(temporaryPath), `${JSON.stringify(next, null, 2)}\n`);
|
||||
fs.renameSync(abs(temporaryPath), abs(checkpointPath));
|
||||
}
|
||||
const run = (command, args = []) => {
|
||||
@@ -112,6 +121,17 @@ const currentTask = () => {
|
||||
if (!task || !parentManifest) throw new Error("queue pointer is incomplete");
|
||||
return { task, parentManifest };
|
||||
};
|
||||
const terminalTask = (task) => {
|
||||
try {
|
||||
const index = JSON.parse(fs.readFileSync(abs("tests/golden/WBV2/task-index.json"), "utf8"));
|
||||
const manifestPath = `tests/golden/${task}/manifest.json`;
|
||||
const manifest = fs.existsSync(abs(manifestPath)) ? JSON.parse(fs.readFileSync(abs(manifestPath), "utf8")) : null;
|
||||
return index.activeTask === null && manifest?.task === task && manifest.status === "done" && manifest.nextTask === null;
|
||||
}
|
||||
catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
const childArgs = ["tools/web/run-wbv2-continuous.mjs", "--max-iterations", "1"];
|
||||
if (commitEnabled) childArgs.push("--commit");
|
||||
if (pushEnabled) childArgs.push("--push");
|
||||
@@ -128,11 +148,11 @@ try {
|
||||
break;
|
||||
}
|
||||
const before = currentTask();
|
||||
const print = run(process.execPath, ["tools/web/print-task-context.mjs"]);
|
||||
const check = run(process.execPath, ["tools/web/check-task-context.mjs"]);
|
||||
appendLog(`preflight task=${before.task} printExit=${print.code} checkExit=${check.code}`);
|
||||
if (print.code !== 0 || check.code !== 0) {
|
||||
writeCheckpoint({ state: "blocked", iteration, current: before, reason: "preflight_failed", printExit: print.code, checkExit: check.code });
|
||||
const context = run(process.execPath, ["tools/web/check-wbv2-context-cache.mjs", "--task", before.task]);
|
||||
appendLog(`preflight task=${before.task} contextExit=${context.code}`);
|
||||
if (context.code !== 0) {
|
||||
recordFailure(root, { task: before.task, phase: "supervisor", reason: "preflight_failed", childExit: context.code });
|
||||
writeCheckpoint({ state: "blocked", iteration, current: before, reason: "preflight_failed", contextExit: context.code });
|
||||
exitCode = 2;
|
||||
break;
|
||||
}
|
||||
@@ -146,11 +166,19 @@ try {
|
||||
}
|
||||
if (child.code !== 0) {
|
||||
const reason = after.task === before.task ? "child_failed_same_task" : "child_failed_after_queue_advance";
|
||||
recordFailure(root, { task: before.task, phase: "supervisor", reason, childExit: child.code });
|
||||
writeCheckpoint({ state: "blocked", iteration: iteration + 1, before, after, reason, childExit: child.code });
|
||||
exitCode = 3;
|
||||
break;
|
||||
}
|
||||
if (after.task === before.task && terminalTask(before.task)) {
|
||||
writeCheckpoint({ state: "complete", iteration: iteration + 1, before, after, childExit: child.code, reason: "terminal_module_complete" });
|
||||
terminalCompleted = true;
|
||||
iteration += 1;
|
||||
break;
|
||||
}
|
||||
if (after.task === before.task) {
|
||||
recordFailure(root, { task: before.task, phase: "supervisor", reason: "child_exited_without_queue_advance", childExit: child.code });
|
||||
writeCheckpoint({ state: "blocked", iteration: iteration + 1, before, after, reason: "child_exited_without_queue_advance", childExit: child.code });
|
||||
exitCode = 4;
|
||||
break;
|
||||
@@ -166,7 +194,7 @@ try {
|
||||
if (stopRequested) {
|
||||
exitCode = stopSignal === "SIGINT" ? 130 : 143;
|
||||
}
|
||||
if (exitCode === 0) {
|
||||
if (exitCode === 0 && !terminalCompleted) {
|
||||
const current = currentTask();
|
||||
writeCheckpoint({ state: maxIterations === 0 ? "running" : "complete", iteration, current });
|
||||
appendLog(`stopped state=${maxIterations === 0 ? "running" : "complete"} iteration=${iteration} current=${current.task}`);
|
||||
|
||||
Reference in New Issue
Block a user