UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

91 lines (90 loc) 4.42 kB
import { h as clearNodeSqliteKyselyCacheForDatabase, t as openNodeSqliteDatabase } from "./node-sqlite-BpQX3W0e.js"; import { a as prepareSqliteReadOnlyLocationSyncInProcess, i as prepareSqliteReadOnlyLocationSync } from "./sqlite-readonly-location-BC9PgENz.js"; import { o as openClawStateDatabaseCache } from "./openclaw-state-db-cache-C7ljO0xP.js"; import { o as OPENCLAW_SQLITE_BUSY_TIMEOUT_MS } from "./openclaw-state-db-contract-DYCYxE4w.js"; import { s as resolveOpenClawStateSqlitePath, t as assertSupportedStateSchemaVersion } from "./openclaw-state-db-schema-version-c1ZL6JGz.js"; import { statSync } from "node:fs"; import path from "node:path"; //#region src/state/openclaw-state-db-readonly.ts /** Missing runtime tables are empty only before state grows beyond checkpoint bootstrap. */ function hasOpenClawStateTablesBeyondStartupCheckpoint(db) { return db.prepare("SELECT 1 FROM main.sqlite_schema WHERE type = 'table' AND name NOT IN ('schema_meta', 'state_leases') LIMIT 1").get() !== void 0; } function resolveReadOnlyPath(options) { return path.resolve(options.path ?? resolveOpenClawStateSqlitePath(options.env ?? process.env)); } function existingPathOrUndefined(pathname) { try { statSync(pathname); return pathname; } catch (error) { if (error.code === "ENOENT") return; throw error; } } function withOpenClawStateDatabaseReadOnlyIfOpen(operation, pathname) { const opened = openClawStateDatabaseCache.getOpenClawStateDatabaseIfOpenAtPath(pathname); if (!opened || opened.db.isTransaction) return { reused: false }; try { assertSupportedStateSchemaVersion(opened.db, pathname); return { reused: true, value: operation(opened) }; } catch (error) { openClawStateDatabaseCache.evictOpenClawStateDatabaseAfterCorruption(opened, error); throw error; } } function withFreshOpenClawStateDatabaseReadOnly(operation, options, pathname, location = pathname) { const env = options.env ?? process.env; openClawStateDatabaseCache.assertOpenClawStateDatabaseFreshOpenAllowedAtPath(pathname, env); const db = openNodeSqliteDatabase(location, { readOnly: true }); try { db.exec(`PRAGMA busy_timeout = ${OPENCLAW_SQLITE_BUSY_TIMEOUT_MS};`); assertSupportedStateSchemaVersion(db, pathname); return operation({ db, path: pathname }); } finally { clearNodeSqliteKyselyCacheForDatabase(db); db.close(); } } /** * Read shared state without joining the writable lifecycle. * * CLI metadata reads can overlap a live Gateway. Keep them off schema repair, * journal-mode setup, checkpoints, and permission mutation owned by writers. */ function withOpenClawStateDatabaseReadOnly(operation, options = {}) { const pathname = resolveReadOnlyPath(options); const reused = withOpenClawStateDatabaseReadOnlyIfOpen(operation, pathname); if (reused.reused) return reused.value; return withFreshOpenClawStateDatabaseReadOnly(operation, options, pathname); } /** Read existing shared state while preserving non-missing filesystem failures. */ function withExistingOpenClawStateDatabaseReadOnly(operation, options = {}) { const pathname = resolveReadOnlyPath(options); const reused = withOpenClawStateDatabaseReadOnlyIfOpen(operation, pathname); if (reused.reused) return reused.value; const existingPath = existingPathOrUndefined(pathname); return existingPath === void 0 ? void 0 : withFreshOpenClawStateDatabaseReadOnly(operation, options, existingPath); } /** Read existing shared state without creating or updating its SQLite sidecars. */ function withExistingOpenClawStateDatabaseArtifactPreservingReadOnly(operation, options = {}) { const pathname = resolveReadOnlyPath(options); const reused = withOpenClawStateDatabaseReadOnlyIfOpen(operation, pathname); if (reused.reused) return reused.value; const existingPath = existingPathOrUndefined(pathname); if (existingPath === void 0) return; const prepared = (openClawStateDatabaseCache.getOpenClawStateDatabaseIfOpenAtPath(pathname) ? prepareSqliteReadOnlyLocationSync : prepareSqliteReadOnlyLocationSyncInProcess)(existingPath); try { return withFreshOpenClawStateDatabaseReadOnly(operation, options, existingPath, prepared.location); } finally { prepared.cleanup(); } } //#endregion export { withOpenClawStateDatabaseReadOnly as i, withExistingOpenClawStateDatabaseArtifactPreservingReadOnly as n, withExistingOpenClawStateDatabaseReadOnly as r, hasOpenClawStateTablesBeyondStartupCheckpoint as t };