openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
106 lines (105 loc) • 4.14 kB
JavaScript
import { c as isRecord } from "../record-coerce-TIsquoVR.mjs";
import { r as assertExistingDatabaseIdentity } from "../sqlite-worker-identity-BRNRpRyc.mjs";
import { n as formatSqliteErrorCodeSuffix } from "../sqlite-error-diagnostics-CWRyv4lz.mjs";
import { s as OPENCLAW_SQLITE_BUSY_TIMEOUT_MS } from "../openclaw-state-db-contract-BYv0nUQr.mjs";
import { a as serializeSqliteFileGeneration } from "../sqlite-file-generation-HEkrmgCv.mjs";
import { constants, setPriority } from "node:os";
//#region src/state/openclaw-database-verify.worker.ts
const DATABASE_VERIFY_CHILD_ARG = "--openclaw-database-verify-child";
function isVerifyTarget(target) {
return isRecord(target) && typeof target.path === "string" && (target.kind === "agent" || target.kind === "state") && typeof target.label === "string" && (target.check === "quick" || target.check === "full") && (target.identity === void 0 || typeof target.identity === "string") && (target.confirm === void 0 || target.confirm === true && target.check === "full");
}
function formatVerifyError(error) {
return `${error instanceof Error ? `${error.name}: ${error.message}` : String(error)}${formatSqliteErrorCodeSuffix(error)}`;
}
async function verifyOpenClawDatabase(target) {
const [integrity, source] = await Promise.all([import("../sqlite-integrity-B-ogZrA2.mjs"), import("../sqlite-source-handle-B_Cgh-Sg.mjs")]);
if (target.confirm) {
const confirmation = integrity.confirmSqliteFileIntegrity(target.path, target.label);
if (confirmation.status === "healthy") return {
path: target.path,
ok: true,
generation: serializeSqliteFileGeneration(confirmation.generation)
};
return {
path: target.path,
ok: false,
error: formatVerifyError(confirmation.error),
terminal: confirmation.terminal,
...confirmation.terminal ? { generation: serializeSqliteFileGeneration(confirmation.generation) } : {}
};
}
const failed = (error) => ({
path: target.path,
ok: false,
error: formatVerifyError(error),
terminal: error instanceof Error && integrity.isTerminalSqliteIntegrityError(error)
});
let result = {
path: target.path,
ok: true
};
try {
const assertIdentity = () => {
if (target.identity) assertExistingDatabaseIdentity(target.path, `file:${target.identity}`);
};
assertIdentity();
source.withSqliteSourceReadDatabase(target.path, "source", (reader) => {
try {
assertIdentity();
reader.exec(`PRAGMA busy_timeout = ${OPENCLAW_SQLITE_BUSY_TIMEOUT_MS}; BEGIN;`);
integrity.assertSqliteIntegrity(reader, target.label, target.check === "full" ? "integrity_check" : "quick_check");
reader.exec("ROLLBACK;");
assertIdentity();
} catch (error) {
result = failed(error);
}
});
} catch (error) {
if (result.ok) result = failed(error);
}
return result;
}
/** Verify database files serially so large agent scans never compete for I/O. */
async function verifyOpenClawDatabases(targets) {
const results = [];
for (const target of targets) results.push(await verifyOpenClawDatabase(target));
return results;
}
const sendToParent = process.argv[2] === DATABASE_VERIFY_CHILD_ARG ? process.send?.bind(process) : void 0;
if (sendToParent) process.once("message", (message) => {
(async () => {
try {
const targets = Array.isArray(message) ? message.filter(isVerifyTarget) : [];
if (targets.some((target) => target.check === "full")) try {
setPriority(process.pid, constants.priority.PRIORITY_LOW);
} catch {}
const results = await verifyOpenClawDatabases(targets);
await new Promise((resolve, reject) => {
sendToParent(results, (error) => {
if (error) reject(error);
else resolve();
});
});
} catch {
process.exitCode = 1;
} finally {
process.disconnect?.();
}
})();
});
if (process.argv[2] === "--openclaw-database-verify-sync" && process.argv[3]) {
const pathname = process.argv[3];
verifyOpenClawDatabases([{
path: pathname,
kind: "agent",
label: pathname,
check: "full"
}]).then(([result]) => {
process.exitCode = result?.ok ? 0 : 1;
}).catch(() => {
process.exitCode = 1;
});
}
//#endregion
export { verifyOpenClawDatabases };