From cd3e2204d0b06ca45d9427cf6e68a95a64f8bb4e Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 2 Aug 2026 23:37:36 +0800 Subject: [PATCH] fix(sqlite): wait for startup checkpoint locks (#118022) --- src/state/openclaw-state-db-startup-checkpoint.ts | 4 ++++ src/state/openclaw-state-db.test.ts | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/state/openclaw-state-db-startup-checkpoint.ts b/src/state/openclaw-state-db-startup-checkpoint.ts index 65acd03bd398..e52afaf59c44 100644 --- a/src/state/openclaw-state-db-startup-checkpoint.ts +++ b/src/state/openclaw-state-db-startup-checkpoint.ts @@ -2,6 +2,7 @@ import type { DatabaseSync } from "node:sqlite"; import { openNodeSqliteDatabase } from "../infra/node-sqlite.js"; import { assertSqliteIntegrity } from "../infra/sqlite-integrity.js"; import { runSqliteImmediateTransactionSync } from "../infra/sqlite-transaction.js"; +import { configureSqlitePreSchemaPragmas } from "../infra/sqlite-wal.js"; import { OPENCLAW_SQLITE_BUSY_TIMEOUT_MS, type OpenClawStateDatabaseOptions, @@ -64,6 +65,9 @@ export function withOpenClawStateStartupMigrationCheckpointDatabase( ensureOpenClawStatePermissions(pathname, env); const db = openNodeSqliteDatabase(pathname); try { + configureSqlitePreSchemaPragmas(db, { + busyTimeoutMs: OPENCLAW_SQLITE_BUSY_TIMEOUT_MS, + }); assertSqliteIntegrity(db, pathname); ensureStartupMigrationCheckpointSchema(db, pathname); return callback(db); diff --git a/src/state/openclaw-state-db.test.ts b/src/state/openclaw-state-db.test.ts index 85beb9ca293d..10473677e41b 100644 --- a/src/state/openclaw-state-db.test.ts +++ b/src/state/openclaw-state-db.test.ts @@ -2819,6 +2819,17 @@ INSERT INTO macos_port_guardian_records VALUES (4242, 18789, '/usr/bin/ssh', 're expect(checkpointCallback).not.toHaveBeenCalled(); }); + it("configures checkpoint lock waits before schema mutation", () => { + const stateDir = createTempStateDir(); + + withOpenClawStateStartupMigrationCheckpointDatabase( + (db) => { + expect(readSqliteNumberPragma(db, "busy_timeout")).toBe(OPENCLAW_SQLITE_BUSY_TIMEOUT_MS); + }, + { env: { OPENCLAW_STATE_DIR: stateDir } }, + ); + }); + it("runs full integrity before a pending state schema migration", () => { const stateDir = createTempStateDir(); const databasePath = createCanonicalAuditStateDatabase(stateDir);