Files
openclaw/src/state/openclaw-database-verify.ts
T
Vito Cappello c15ab158b0 fix(state): preserve live SQLite WAL files during verification (#114016)
* fix(state): isolate database verifier snapshots

* test(state): assert verifier retains POSIX lock

* fix(state): scope verifier child IPC

---------

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-26 20:57:17 -04:00

67 lines
1.9 KiB
TypeScript

import type { ChildProcess } from "node:child_process";
import { createSubsystemLogger } from "../logging/subsystem.js";
import {
applyOpenClawDatabaseVerificationResults,
collectOpenClawDatabaseVerifyTargets,
OPENCLAW_DATABASE_VERIFY_INITIAL_DELAY_MS,
OPENCLAW_DATABASE_VERIFY_INTERVAL_MS,
runDatabaseVerifyWorker,
terminateDatabaseVerifyWorker,
} from "./openclaw-database-verify.impl.js";
const log = createSubsystemLogger("state/database-verify");
/** Start the Gateway-owned delayed daily integrity verifier. */
export function startOpenClawDatabaseIntegrityVerifier(options: { env: NodeJS.ProcessEnv }): {
stop: () => Promise<void>;
} {
let activeWorker: ChildProcess | undefined;
let stopped = false;
let timer: ReturnType<typeof setTimeout> | undefined;
const schedule = (delayMs: number) => {
timer = setTimeout(() => void run(), delayMs);
timer.unref?.();
};
const run = async () => {
timer = undefined;
try {
const targets = collectOpenClawDatabaseVerifyTargets(options);
if (targets.length > 0) {
const results = await runDatabaseVerifyWorker(targets, {
onWorker: (worker) => {
activeWorker = worker;
},
});
if (!stopped) {
applyOpenClawDatabaseVerificationResults({ ...options, results, targets });
}
}
} catch (error) {
if (!stopped) {
log.error("database integrity verifier failed", { error: String(error) });
}
} finally {
activeWorker = undefined;
if (!stopped) {
schedule(OPENCLAW_DATABASE_VERIFY_INTERVAL_MS);
}
}
};
schedule(OPENCLAW_DATABASE_VERIFY_INITIAL_DELAY_MS);
return {
stop: async () => {
stopped = true;
if (timer) {
clearTimeout(timer);
timer = undefined;
}
if (activeWorker) {
await terminateDatabaseVerifyWorker(activeWorker);
}
activeWorker = undefined;
},
};
}