UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

106 lines (105 loc) • 5.44 kB
import { a as getNodeSqliteKysely, r as executeSqliteQuerySync } from "./kysely-sync-K7ftY-g4.mjs"; import { t as clearNodeSqliteKyselyCacheForDatabase } from "./kysely-sync-cache-state-eUau8Jaa.mjs"; import { t as openNodeSqliteDatabase } from "./node-sqlite-XIcwmOrl.mjs"; import { r as OpenClawStateOwnershipMetadataError } from "./sqlite-lifecycle-errors-DuOygjcn.mjs"; import { s as OPENCLAW_SQLITE_BUSY_TIMEOUT_MS } from "./openclaw-state-db-contract-Cm9fKF2T.mjs"; import { a as runSqliteImmediateTransactionSync } from "./sqlite-transaction-DsZ3X6nD.mjs"; import { i as configureSqliteWalMaintenance } from "./sqlite-wal-DUSYRhyv.mjs"; import { r as resolveDatabasePath } from "./openclaw-state-db.paths-DfifnSGp.mjs"; import { i as assertStateDatabaseAccessAllowed } from "./gateway-state-owner-DmHycK5o.mjs"; import { b as assertOpenClawStateDatabaseForMaintenance } from "./openclaw-state-db-fast-path-CPAamWzU.mjs"; import { o as isGatewayExternallySupervised } from "./gateway-supervision-CUdBruRD.mjs"; import { n as assertSqliteIntegrity } from "./sqlite-integrity-GtqcmwG3.mjs"; import { f as openClawStateDatabaseCache } from "./openclaw-state-db-cache-BKCnj4of.mjs"; import { a as inspectOpenClawStateOwnershipFromDatabase, c as normalizeOpenClawStateManagerId, t as STATE_SUPERVISION_KEY } from "./openclaw-state-ownership-BDcUGGMF.mjs"; import { l as runOpenClawStateWriteTransaction, r as openOpenClawStateDatabase } from "./openclaw-state-db-D1jWDzK3.mjs"; //#region src/state/openclaw-state-ownership-operations.ts function requireOwnershipCheckpoint(walMaintenance, databasePath) { if (!walMaintenance.checkpoint()) throw new Error(`External ownership was committed for ${databasePath}, but its WAL checkpoint failed. Retry the same ownership claim before activating the supervisor.`); } function claimOwnershipRow(database, databasePath, managerId, repairMalformed) { let current = null; try { current = inspectOpenClawStateOwnershipFromDatabase(database, databasePath); } catch (error) { if (!repairMalformed || !(error instanceof OpenClawStateOwnershipMetadataError)) throw error; } if (current) { if (current.managerId !== managerId) throw new Error(`OpenClaw shared state is already claimed by external manager ${current.managerId}; manager ${managerId} cannot replace that durable ownership.`); return current; } const ownership = { version: 1, mode: "external", managerId, claimedAt: Date.now() }; const valueJson = JSON.stringify(ownership); const stateDb = getNodeSqliteKysely(database); executeSqliteQuerySync(database, stateDb.insertInto("config_machine_state").values({ state_key: STATE_SUPERVISION_KEY, value_json: valueJson, updated_at_ms: ownership.claimedAt }).onConflict((conflict) => conflict.column("state_key").doUpdateSet({ value_json: valueJson, updated_at_ms: ownership.claimedAt }))); return ownership; } function repairMalformedOwnershipClaim(databasePath, managerId) { assertStateDatabaseAccessAllowed(databasePath); const existing = openClawStateDatabaseCache.getOpenClawStateDatabaseIfOpenAtPath(databasePath); const database = existing?.db ?? openNodeSqliteDatabase(databasePath); let walMaintenance; try { database.exec(`PRAGMA busy_timeout = ${OPENCLAW_SQLITE_BUSY_TIMEOUT_MS};`); assertSqliteIntegrity(database, databasePath); assertOpenClawStateDatabaseForMaintenance(database, { pathname: databasePath }); walMaintenance = existing?.walMaintenance ?? configureSqliteWalMaintenance(database, { busyTimeoutMs: 5e3, checkpointIntervalMs: 0, checkpointMode: "TRUNCATE", databaseLabel: "OpenClaw shared state ownership", databasePath }); const ownership = runSqliteImmediateTransactionSync(database, () => { assertStateDatabaseAccessAllowed(databasePath); assertOpenClawStateDatabaseForMaintenance(database, { pathname: databasePath }); return claimOwnershipRow(database, databasePath, managerId, true); }, { busyTimeoutMs: OPENCLAW_SQLITE_BUSY_TIMEOUT_MS, databaseLabel: databasePath, operationLabel: "state.ownership.repair" }); requireOwnershipCheckpoint(walMaintenance, databasePath); return ownership; } finally { if (!existing) { walMaintenance?.close({ checkpointMode: "PASSIVE" }); clearNodeSqliteKyselyCacheForDatabase(database); database.close(); } } } /** Claim durable shared-state write ownership for the active external supervisor. */ function claimOpenClawStateOwnership(managerId, options = {}) { const env = options.env ?? process.env; if (!isGatewayExternallySupervised(env)) throw new Error("Claiming external shared-state ownership requires OPENCLAW_SUPERVISOR_MODE=external."); const normalizedManagerId = normalizeOpenClawStateManagerId(managerId); try { const database = openOpenClawStateDatabase(options); const ownership = runOpenClawStateWriteTransaction(({ db, path: databasePath }) => claimOwnershipRow(db, databasePath, normalizedManagerId, false), { ...options, database }, { operationLabel: "state.ownership.claim" }); requireOwnershipCheckpoint(database.walMaintenance, database.path); return ownership; } catch (error) { if (!(error instanceof OpenClawStateOwnershipMetadataError)) throw error; const ownership = repairMalformedOwnershipClaim(resolveDatabasePath(options), normalizedManagerId); openOpenClawStateDatabase(options); return ownership; } } //#endregion export { claimOpenClawStateOwnership };