openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
245 lines (244 loc) • 11.7 kB
JavaScript
import { i as extractErrorCode, r as collectNestedErrorCandidates } from "./error-coercion-CvJK4lmH.mjs";
import { t as createDeferredCore } from "./deferred-D0La5CRk.mjs";
import { a as resolveGlobalSingleton } from "./global-singleton-0m-JziJW.mjs";
import { c as isRecord } from "./record-coerce-TIsquoVR.mjs";
import { t as isPromiseLike } from "./promise-like-D7-l5Fsp.mjs";
import { a as createSqliteLifecycleAggregateError } from "./sqlite-lifecycle-errors-DuOygjcn.mjs";
import { n as OpenClawStateLeaseError } from "./openclaw-state-lease-error-Ds9BTWol.mjs";
import { c as SqliteWorkerError } from "./sqlite-worker-contract-C51cJHzg.mjs";
import { n as createSqliteWorkerOperationAdmission } from "./sqlite-worker-operation-admission-cNGSH5v0.mjs";
import { isDeepStrictEqual } from "node:util";
//#region src/state/openclaw-state-lease-worker-owner.ts
const owners = resolveGlobalSingleton(Symbol.for("openclaw.stateLeaseWorkerOwners"), () => /* @__PURE__ */ new WeakMap());
function ownershipRefused() {
throw new OpenClawStateLeaseError("State lease worker ownership was refused", { code: "OPENCLAW_STATE_LEASE_LOST" });
}
function assertSynchronousAuthority(assertion) {
const result = assertion?.();
if (isPromiseLike(result)) {
Promise.resolve(result).catch(() => {});
throw new Error("State lease worker authority must complete synchronously");
}
}
function captureLeaseWorkerSource(context, databasePath) {
const { admission, maintenanceScope, runInCapturedSchemaScope, existingSchemaPath, environment } = context;
const sourceEnvironment = { ...environment };
const assertAdmission = admission.assertCurrent;
const assertMaintenance = maintenanceScope?.assertAdmission;
const assertMaintenanceOwner = maintenanceScope?.assertOwnerCurrent;
return () => {
if (context.admission !== admission || admission.databasePath !== databasePath || admission.assertCurrent !== assertAdmission || context.maintenanceScope !== maintenanceScope || maintenanceScope?.assertAdmission !== assertMaintenance || maintenanceScope?.assertOwnerCurrent !== assertMaintenanceOwner || context.runInCapturedSchemaScope !== runInCapturedSchemaScope || context.existingSchemaPath !== existingSchemaPath || context.environment !== environment || !isDeepStrictEqual(environment, sourceEnvironment)) throw new Error("State lease worker source binding was replaced");
assertMaintenance?.();
assertAdmission();
};
}
function createLeaseAdmissionFactory(scopes, purpose, assertCurrent, beforeCommit, options = {}) {
const firstScope = scopes[0];
if (!firstScope) throw new Error("State lease admission requires a retained owner");
return (retained) => {
assertCurrent();
for (const scope of scopes) scope.retainSettlement(retained.settled);
retained.settled.then((outcome) => {
for (const scope of scopes) scope.settleNative(retained.settled, outcome);
});
let writeStage = "waiting";
let lifecycleStage = "transaction";
const lifecycleWrite = purpose === "acquire" || purpose === "renew" || purpose === "release";
const expiryRequired = purpose === "write" || purpose === "verify" || purpose === "renew";
return {
nativeLocations: [...new Set(scopes.map((scope) => scope.databasePath))],
admission: createSqliteWorkerOperationAdmission((request, grant) => {
assertCurrent();
const facts = request.facts;
const kind = options.plural ? "state-leases" : purpose === "write" ? "state-lease" : `state-lease-${purpose}`;
if ((purpose === "write" ? writeStage === "commit" || options.plural && request.stage === "transaction" && writeStage !== "waiting" || request.stage !== "transaction" && !(request.stage === "commit" && writeStage === "transaction") : lifecycleWrite ? request.stage !== lifecycleStage : request.stage !== "transaction") || !isRecord(facts) || facts.kind !== kind) ownershipRefused();
const members = options.plural ? facts.leases : [facts];
if (!Array.isArray(members) || members.length !== scopes.length) ownershipRefused();
const assertFacts = () => {
const now = Date.now();
for (const [index, scope] of scopes.entries()) {
const member = members[index];
if (!isRecord(member) || !isDeepStrictEqual(member.identity, scope.identity) || expiryRequired && (typeof member.expiresAt !== "number" || !Number.isFinite(member.expiresAt) || member.expiresAt <= now)) ownershipRefused();
}
};
assertFacts();
if (purpose === "write" && request.stage === "commit") {
writeStage = "commit";
beforeCommit?.();
assertCurrent();
assertFacts();
}
if (grant()) {
if (lifecycleWrite) lifecycleStage = lifecycleStage === "transaction" ? "commit" : "settled";
else if (purpose === "write" && request.stage === "transaction") writeStage = "transaction";
}
}, options.expiryObservation && (purpose === "acquire" || purpose === "verify" || purpose === "renew") ? {
kind: "state-lease-expiry",
identity: firstScope.identity,
observation: options.expiryObservation
} : void 0)
};
};
}
function runRetainedLeaseScopes(scopes, operation) {
const result = (async () => {
try {
const value = await operation();
for (const scope of scopes) scope.rethrowIfUncertain(void 0, void 0);
return value;
} catch (failure) {
for (const scope of scopes) scope.rethrowIfUncertain(failure, void 0);
throw failure;
} finally {
for (const scope of scopes) scope.finish();
}
})();
result.catch(() => {});
return result;
}
/** Registered only by the actual lease owner, never reconstructed from a receipt. */
function createOpenClawStateLeaseWorkerOwner(params) {
const assertSourceCurrent = params.sourceContext ? captureLeaseWorkerSource(params.sourceContext, params.databasePath) : void 0;
const pending = /* @__PURE__ */ new Set();
const settlements = /* @__PURE__ */ new Set();
let accepting = true;
let closed = false;
let uncertain;
const unknownOutcome = (cause) => Object.assign(new SqliteWorkerError("State lease worker transaction outcome is unknown", "outcome-unknown"), { cause });
const assertCurrent = (purpose) => {
if (uncertain) throw uncertain.error;
if (closed) throw new OpenClawStateLeaseError("State lease worker admission is closed", { code: "OPENCLAW_STATE_LEASE_LOST" });
params.assertCurrent(purpose);
};
const rethrowIfUncertain = (failure, authorityError) => {
const uncertainty = uncertain?.error ?? collectNestedErrorCandidates(failure).find((candidate) => extractErrorCode(candidate) === "outcome-unknown");
if (uncertainty === void 0) return;
const errors = [...new Set([
uncertainty,
failure,
...authorityError === void 0 ? [] : [authorityError]
].filter((error) => error !== void 0))];
if (errors.length === 1) throw uncertainty instanceof Error ? uncertainty : unknownOutcome(uncertainty);
throw unknownOutcome(createSqliteLifecycleAggregateError(errors, "state lease operation has an unknown write outcome", uncertainty));
};
const owner = {
identity: params.identity,
sourceContext: params.sourceContext,
assertSourceCurrent() {
if (!assertSourceCurrent) throw new Error("State leases require their original shared source context");
assertSourceCurrent();
},
retain(databasePath, purpose, authority) {
const assertCaller = authority?.assertCurrent;
assertCurrent(purpose);
if (!accepting && purpose !== "release" && purpose !== "verify" || databasePath !== params.databasePath) throw new Error("State lease worker operation differs from its live owner");
const completion = createDeferredCore();
pending.add(completion.promise);
let active = true;
return {
identity: params.identity,
databasePath: params.databasePath,
assertCurrent() {
assertCurrent(purpose);
assertCaller?.();
if (!active) throw new Error("State lease worker operation has settled");
},
retainSettlement(settled) {
settlements.add(settled);
},
settleNative(settled, settlement) {
if (settlement.kind === "unknown") {
uncertain ??= { error: unknownOutcome(settlement.error) };
accepting = false;
}
settlements.delete(settled);
},
rethrowIfUncertain,
finish() {
active = false;
pending.delete(completion.promise);
completion.resolve();
}
};
},
run(databasePath, operation, purpose, authority) {
const beforeCommit = authority?.beforeCommit;
const scope = owner.retain(databasePath, purpose, authority);
return runRetainedLeaseScopes([scope], () => operation({
identity: { ...scope.identity },
assertCurrent: scope.assertCurrent,
createAdmission: createLeaseAdmissionFactory([scope], purpose, scope.assertCurrent, beforeCommit, { expiryObservation: params.expiryObservation })
}));
}
};
let boundLease = params.lease;
if (boundLease) owners.set(boundLease, owner);
const settle = async () => {
accepting = false;
await Promise.allSettled(pending);
await Promise.allSettled(settlements);
};
return {
bind(lease) {
if (closed || boundLease) throw new Error("State lease worker owner is already bound or closed");
boundLease = lease;
owners.set(lease, owner);
},
runLifecycle(purpose, operation) {
return owner.run(params.databasePath, operation, purpose);
},
run(operation) {
return owner.run(params.databasePath, operation, "write");
},
canRelease: () => pending.size === 0 && settlements.size === 0 && !uncertain,
settle,
rethrowIfUncertain,
async drain() {
await settle();
if (uncertain) throw uncertain.error;
},
close() {
accepting = false;
closed = true;
if (boundLease) owners.delete(boundLease);
}
};
}
function withOpenClawStateLeaseWorkerAdmission(lease, databasePath, operation, authority) {
const owner = owners.get(lease);
if (!owner) throw new Error("State lease worker operation requires its original live lease context");
return owner.run(databasePath, operation, "write", authority);
}
/** Multiple leases authorize one worker operation only from their shared captured source. */
function withOpenClawStateLeasesWorkerAdmission(leases, context, operation, authority) {
if (leases.length === 0) throw new Error("State lease worker operation requires at least one live lease");
const assertCaller = authority?.assertCurrent;
const beforeCommit = authority?.beforeCommit;
const selected = leases.map((lease) => {
const owner = owners.get(lease);
if (!owner || owner.sourceContext !== context) throw new Error("State leases require their original shared source context");
return owner;
});
const keys = new Set(selected.map(({ identity }) => JSON.stringify([identity.scope, identity.key])));
if (new Set(selected).size !== selected.length || keys.size !== selected.length) throw new Error("State lease worker operation contains duplicate leases");
const scopes = [];
const assertCurrent = () => {
assertSynchronousAuthority(assertCaller);
for (const scope of scopes) scope.assertCurrent();
for (const owner of selected) owner.assertSourceCurrent();
};
try {
for (const owner of selected) scopes.push(owner.retain(context.admission.databasePath, "write"));
assertCurrent();
} catch (error) {
for (const scope of scopes) scope.finish();
throw error;
}
return runRetainedLeaseScopes(scopes, () => operation({
identities: scopes.map(({ identity }) => ({ ...identity })),
assertCurrent,
createAdmission: createLeaseAdmissionFactory(scopes, "write", assertCurrent, () => assertSynchronousAuthority(beforeCommit), { plural: true })
}));
}
//#endregion
export { withOpenClawStateLeaseWorkerAdmission as n, withOpenClawStateLeasesWorkerAdmission as r, createOpenClawStateLeaseWorkerOwner as t };