UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

125 lines (124 loc) • 6.67 kB
import { n as computeBackoff } from "./src-DqaLEvc_.mjs"; import { t as extractSqliteTableSchema } from "./sqlite-schema-sql-CKIqAlrf.mjs"; import { r as runWithSqliteBusyTimeout } from "./sqlite-busy-timeout-DYrW2wFu.mjs"; import { a as isSqliteLockError } from "./sqlite-error-diagnostics-mpIpHclY.mjs"; import { s as resolveOpenClawStateSqlitePath } from "./openclaw-state-db.paths-BvBEgHyD.mjs"; import "./backoff-DG9ukw7j.mjs"; import { p as withOpenClawStateDatabaseReadOnly } from "./openclaw-state-db-readonly-BLZyK3So.mjs"; import { p as OPENCLAW_STATE_SCHEMA_SQL } from "./openclaw-state-db-legacy-backfills-D9u-q2VB.mjs"; import { a as createOpenClawStateLeaseLostError, n as OpenClawStateLeaseError, s as toOpenClawStateLeaseVerificationError } from "./openclaw-state-lease-error-Ds9BTWol.mjs"; import { r as captureOpenClawStateWorkerContext } from "./openclaw-state-worker-context-epCM4Gdh.mjs"; import { l as runOpenClawStateWriteTransaction, r as openOpenClawStateDatabase, u as runWithOpenClawStateBusyTimeout } from "./openclaw-state-db-VZFEEleX.mjs"; import { a as releaseOpenClawStateLeaseInTransaction, o as renewOpenClawStateLeaseInTransaction, r as readOpenClawStateLeaseExpiry } from "./openclaw-state-lease-store-DU9l42Vs.mjs"; import { n as createSqliteWorkerWriteAdmission } from "./sqlite-worker-store-DqYxJvP-.mjs"; import { a as runOpenClawStateWorkerOperation } from "./openclaw-state-worker-store-C_wo5SMW.mjs"; import { t as runExistingOpenClawStateWriteTransaction } from "./openclaw-state-db-existing-write-5xke2dyd.mjs"; import path from "node:path"; import { setTimeout } from "node:timers/promises"; //#region src/state/openclaw-state-lease-storage.ts const leaseSchema = ["schema_meta", "state_leases"].map((table) => extractSqliteTableSchema(OPENCLAW_STATE_SCHEMA_SQL, table, { endMarker: ") STRICT;", errorMessage: "Existing lease schema is unavailable." })).join("\n"); function prepareLeaseDatabase(database) { if (database.schemaPolicy !== "existing") runWithOpenClawStateBusyTimeout(() => void 0, database.options ?? {}, 0); } function resolveLeaseDatabasePath(database) { return database.schemaPolicy === "existing" ? path.resolve(database.options?.path ?? resolveOpenClawStateSqlitePath(database.options?.env)) : openOpenClawStateDatabase(database.options).path; } function readLeaseDatabase(database, operation) { return database.schemaPolicy === "existing" ? withOpenClawStateDatabaseReadOnly(({ db }) => operation(db), database.options) : operation(openOpenClawStateDatabase(database.options).db); } async function acquireLease(database, input, assertCurrent, signal) { if (database.options?.readOnly) throw new Error("State lease acquisition requires writable storage"); if (database.schemaPolicy === "existing" && database.options?.database) throw new Error("Existing-state writes require their own tracked writable connection."); const opened = database.schemaPolicy === "existing" ? void 0 : openOpenClawStateDatabase(database.options); const context = captureOpenClawStateWorkerContext({ ...database.options, path: opened?.path ?? resolveLeaseDatabasePath(database) }); const assertAdmission = () => { context.admission.assertCurrent(); assertCurrent(); if (opened?.db.isTransaction) throw new OpenClawStateLeaseError("State lease acquisition requires no active transaction", { code: "OPENCLAW_STATE_LEASE_INVALID_INPUT" }); }; const result = await runOpenClawStateWorkerOperation(context, (scope) => scope.execute({ type: "stateLease.acquire", input: { ...input, schemaPolicy: database.schemaPolicy } }, { signal }), { existingOnly: database.schemaPolicy === "existing", assertCurrent: assertAdmission, createAdmission: createSqliteWorkerWriteAdmission(assertAdmission, [context.admission.databasePath]) }); if (!result) throw new Error("State lease acquisition requires an existing database"); return result; } function withLeaseWriteTransaction(database, operationLabel, operation, busyTimeoutMs = 0) { if (database.schemaPolicy === "existing") return runExistingOpenClawStateWriteTransaction(({ db }) => operation(db), database.options ?? {}, { operationLabel, busyTimeoutMs, schemaSql: leaseSchema }); const stateDatabase = openOpenClawStateDatabase(database.options); const run = () => runOpenClawStateWriteTransaction(({ db }) => operation(db), { ...database.options, database: stateDatabase }, { operationLabel, busyTimeoutMs }); return runWithSqliteBusyTimeout(stateDatabase.db, busyTimeoutMs, run); } const STATE_LEASE_WRITE_BACKOFF = { initialMs: 25, maxMs: 250, factor: 1.5, jitter: .25 }; const RELEASE_RETRY_TIMEOUT_MS = 2e3; function renewOpenClawStateLease(params) { return withLeaseWriteTransaction(params.database, params.operationLabel, (db) => { const expiresAt = renewOpenClawStateLeaseInTransaction(db, params, params.leaseMs); if (expiresAt === void 0) throw createOpenClawStateLeaseLostError(params); return expiresAt; }); } function assertOpenClawStateLeaseOwnedInDatabase(database, params) { const expiresAt = readOpenClawStateLeaseExpiry(database, params); if (expiresAt === void 0) throw createOpenClawStateLeaseLostError(params); return expiresAt; } function verifyOpenClawStateLeaseOwnership(params) { try { if (params.transaction) return assertOpenClawStateLeaseOwnedInDatabase(params.transaction, params); if (!params.database) throw new Error("state lease ownership check requires a database"); return readLeaseDatabase(params.database, (db) => assertOpenClawStateLeaseOwnedInDatabase(db, params)); } catch (error) { throw toOpenClawStateLeaseVerificationError(params, error); } } function releaseOpenClawStateLease(params) { withLeaseWriteTransaction(params.database, params.operationLabel, (db) => releaseOpenClawStateLeaseInTransaction(db, params)); } async function releaseOpenClawStateLeaseBestEffort(params, execute) { const deadline = performance.now() + RELEASE_RETRY_TIMEOUT_MS; let attempt = 0; while (true) try { if (execute) await execute(); else releaseOpenClawStateLease(params); return; } catch (error) { const now = performance.now(); if (!isSqliteLockError(error) || now >= deadline) { if (execute) throw error; return; } attempt += 1; await setTimeout(Math.min(deadline - now, computeBackoff(STATE_LEASE_WRITE_BACKOFF, attempt))); } } //#endregion export { releaseOpenClawStateLeaseBestEffort as a, verifyOpenClawStateLeaseOwnership as c, releaseOpenClawStateLease as i, withLeaseWriteTransaction as l, acquireLease as n, renewOpenClawStateLease as o, prepareLeaseDatabase as r, resolveLeaseDatabasePath as s, STATE_LEASE_WRITE_BACKOFF as t };