接续L4-TOOL-DB持久化闭环

结论:真实 Node/native DB_PROGRAM transcript 与 flat-file 已接入 Tool DB OPFS store 证据链,浏览器执行仍保持锁定等待 Python/WASM Worker。
This commit is contained in:
2026-06-19 07:01:48 +08:00
parent 823bab5fa4
commit d323511f8b
6 changed files with 181 additions and 18 deletions

View File

@@ -569,6 +569,10 @@ private module paths:
LinuxCNC-owned tool DB process port contract. Contract-only mode does not run
`DB_PROGRAM`, does not parse `.tbl` as a fallback, and keeps execution and
promotion disabled.
- `runToolDbProcessPortPersistenceSession()` for running a supplied tool DB
process port, persisting its transcript and DB flat file through the OPFS tool
DB store, and returning diagnostics. The helper is browser-safe glue; runtime
semantics still come from the supplied port adapter.
- `createLinuxCncToolDbNodeRuntimeAdapter()` in
`runtime/sdk/src/tool-db-node-runtime-adapter.js` for Node/native verification
of the real LinuxCNC `DB_PROGRAM` child process. This adapter is intentionally

View File

@@ -99,6 +99,9 @@ export {
createToolDbTransactionPlan,
validateToolDbTranscript,
} from "./tool-db-process-port.js";
export {
runToolDbProcessPortPersistenceSession,
} from "./tool-db-runtime-session.js";
export {
defaultMachinePaths,

View File

@@ -1,5 +1,5 @@
import { createWriteStream } from "node:fs";
import { mkdir, rm } from "node:fs/promises";
import { mkdir, readFile, rm } from "node:fs/promises";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { spawn } from "node:child_process";
@@ -156,5 +156,9 @@ export function createLinuxCncToolDbNodeRuntimeAdapter({
stdoutFile?.end();
stderrFile?.end();
},
async readDbFileText() {
return readFile(dbSavefile, "utf8");
},
};
}

View File

@@ -0,0 +1,78 @@
import {
loadToolDbFile,
loadToolDbTranscript,
saveToolDbFile,
saveToolDbTranscript,
} from "../../opfs/tool-db-store.js";
import {
createToolDbProcessDiagnostics,
createToolDbTransactionPlan,
validateToolDbTranscript,
} from "./tool-db-process-port.js";
function requireString(value, label) {
if (typeof value !== "string" || value.length === 0) {
throw new Error(`${label} must be a non-empty string.`);
}
return value;
}
export async function runToolDbProcessPortPersistenceSession({
port,
machineId,
runId = "run-1",
dbProgramPath = "./db_nonran.py",
dbFileText,
storage,
plan = createToolDbTransactionPlan(),
startupToolCount = 10,
mutationCount = 3,
readDbFileText = null,
} = {}) {
if (!port?.start || !port?.runTransactionPlan || !port?.exportTranscript || !port?.close) {
throw new Error("port must be a ToolDbProcessPort-like object.");
}
requireString(machineId, "machineId");
requireString(runId, "runId");
requireString(dbProgramPath, "dbProgramPath");
const startResult = await port.start();
const planResult = await port.runTransactionPlan(plan);
const transcript = port.exportTranscript();
const validation = validateToolDbTranscript(transcript);
const resolvedDbFileText = readDbFileText ? await readDbFileText() : (dbFileText ?? "");
await port.close();
const savedDb = await saveToolDbFile(machineId, resolvedDbFileText, { storage });
const savedTranscript = await saveToolDbTranscript(machineId, runId, transcript, { storage });
const loadedDb = await loadToolDbFile(machineId, { storage });
const loadedTranscript = await loadToolDbTranscript(machineId, runId, { storage });
const diagnostics = createToolDbProcessDiagnostics({
dbProgramPath,
opfsDbPath: savedDb.displayPath,
transcript,
dbFileText: loadedDb.text,
startupToolCount,
mutationCount,
runtimeMode: startResult.runtimeMode,
runtimeExecutionReady: startResult.runtimeExecutionReady === true && planResult.runtimeExecutionReady === true,
});
return {
apiName: "linuxcnc-tool-db-process-runtime-persistence-session",
ready: validation.ready &&
diagnostics.runtimeExecutionReady === true &&
diagnostics.opfsPersistenceReady === true &&
diagnostics.protocolTranscriptReady === true,
startResult,
planResult,
validation,
savedDb,
savedTranscript,
loadedDb,
loadedTranscript,
diagnostics,
executionEnabled: false,
promotionAllowed: false,
};
}