fix: 用容器生命周期核实恢复并单列三份总体验收
审阅发现spawn后快照早于恢复实际执行,不能证明没有重启;改用杀前至目标结果落账的Docker历史事件,保留缓存完整性限制。逐份stats不再冒称任务书总体通过;独立验收要求三份不同研究、成功杀进程及不重叠区间。两项缺陷附回归,7项定向测试与check通过,独立复审无新问题;真实B尚待启动。
This commit is contained in:
+86
-5
@@ -1,5 +1,5 @@
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { appendFileSync, existsSync, mkdirSync } from "node:fs";
|
||||
import { appendFileSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
|
||||
import { join, resolve } from "node:path";
|
||||
import { forwardAccounts, frozenConfig, jsonFile } from "../lib/forward.ts";
|
||||
import { ofKind, readLedger } from "../lib/ledger.ts";
|
||||
@@ -40,6 +40,10 @@ const config =
|
||||
name,
|
||||
null,
|
||||
);
|
||||
const daemonTime = () =>
|
||||
execFileSync("docker", ["info", "--format", "{{.SystemTime}}"], {
|
||||
encoding: "utf8",
|
||||
}).trim();
|
||||
const inspect = (container: string) =>
|
||||
JSON.parse(
|
||||
execFileSync("docker", ["inspect", container], {
|
||||
@@ -130,6 +134,8 @@ try {
|
||||
if (started !== undefined) {
|
||||
// 容器名是正式入口记录在结构文档里的约定,不 import flow 内部文件。
|
||||
const container = `inforsi-${name}-${run}`;
|
||||
// 从杀前划定历史事件区间,覆盖恢复启动到目标结果落账;不把 spawn 当成恢复已执行。
|
||||
const lifecycleSince = daemonTime();
|
||||
const before = inspect(container);
|
||||
jsonFile(
|
||||
join(
|
||||
@@ -208,20 +214,95 @@ try {
|
||||
afterKill,
|
||||
);
|
||||
observe("after-kill");
|
||||
active = start(null);
|
||||
const afterResume = inspect(container);
|
||||
jsonFile(
|
||||
join(
|
||||
out,
|
||||
"container-after-resume.json",
|
||||
"container-before-resume.json",
|
||||
),
|
||||
afterResume,
|
||||
inspect(container),
|
||||
);
|
||||
jsonFile(
|
||||
join(
|
||||
out,
|
||||
"container-events-window.json",
|
||||
),
|
||||
{
|
||||
since: lifecycleSince,
|
||||
until: null,
|
||||
run,
|
||||
resultSeq: null,
|
||||
},
|
||||
);
|
||||
active = start(null);
|
||||
watching = watchTimeline(
|
||||
studyDir,
|
||||
active.child,
|
||||
join(out, "timeline.jsonl"),
|
||||
);
|
||||
let targetResult;
|
||||
while (true) {
|
||||
targetResult = ofKind(
|
||||
readLedger(studyDir),
|
||||
"runResult",
|
||||
).find(
|
||||
(r) =>
|
||||
r.content
|
||||
.run ===
|
||||
run,
|
||||
);
|
||||
if (
|
||||
targetResult !==
|
||||
undefined ||
|
||||
active.child
|
||||
.exitCode !==
|
||||
null ||
|
||||
active.child
|
||||
.signalCode !==
|
||||
null
|
||||
)
|
||||
break;
|
||||
await sleep(100);
|
||||
}
|
||||
const lifecycleUntil = daemonTime();
|
||||
// Docker CLI 按时间回读,不依赖事件订阅的启动时序;原文全存,stats 核对缓存上限和目标 die。
|
||||
const events = execFileSync(
|
||||
"docker",
|
||||
[
|
||||
"events",
|
||||
"--since",
|
||||
lifecycleSince,
|
||||
"--until",
|
||||
lifecycleUntil,
|
||||
"--format",
|
||||
"{{json .}}",
|
||||
],
|
||||
{ encoding: "utf8" },
|
||||
);
|
||||
writeFileSync(
|
||||
join(
|
||||
out,
|
||||
"container-events.jsonl",
|
||||
),
|
||||
events,
|
||||
);
|
||||
jsonFile(
|
||||
join(
|
||||
out,
|
||||
"container-events-window.json",
|
||||
),
|
||||
{
|
||||
since: lifecycleSince,
|
||||
until: lifecycleUntil,
|
||||
run,
|
||||
resultSeq:
|
||||
targetResult?.seq ??
|
||||
null,
|
||||
},
|
||||
);
|
||||
if (targetResult === undefined)
|
||||
throw new Error(
|
||||
"恢复进程没有交出目标结果,生命周期证据不完整;保留现场",
|
||||
);
|
||||
hit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user