openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
135 lines (134 loc) • 4.43 kB
JavaScript
import { t as createDeferredCore } from "./deferred-D0La5CRk.mjs";
import { t as assertExistingDatabaseIdentity } from "./sqlite-worker-identity-B_aK_kcL.mjs";
import { s as throwSqliteLifecycleErrors } from "./sqlite-lifecycle-errors-DuOygjcn.mjs";
import { S as retainOpenClawStateDatabaseForIndependentRead, _ as registerOpenClawStateDatabaseAsyncResource } from "./openclaw-state-db-cache-BEArcjbO.mjs";
import { t as createOpenClawStateReadTransport } from "./openclaw-state-read-worker-nbwoKO-4.mjs";
//#region src/state/openclaw-state-settlement-read.ts
/** A fixed read completes an accepted mutation; it grants no new write or path admission. */
async function withOpenClawStateSettlementRead(context, operation) {
context.admission.assertCurrent();
context.maintenanceScope?.assertAdmission();
const pathname = context.admission.databasePath;
const identity = { ...context.admission.identity };
let borrowed = retainOpenClawStateDatabaseForIndependentRead(pathname);
const producer = createDeferredCore();
const controller = new AbortController();
let active = true;
let pending = false;
let selected;
let transport;
let recovery;
let closing;
const authority = {
signal: controller.signal,
assertCurrent() {
if (!active) throw new Error("Shared-state settlement read has released its owner");
borrowed?.assertCurrent();
assertExistingDatabaseIdentity(pathname, identity.key);
}
};
const recover = () => recovery ??= (async () => {
if (!pending || !selected) return;
if ((await selected.settlement).kind === "not-entered") {
pending = false;
return;
}
if (transport) {
await transport.close();
transport = void 0;
}
authority.assertCurrent();
const readTransport = createOpenClawStateReadTransport(selected.command);
transport = readTransport;
let result;
const errors = [];
try {
result = await readTransport.read({
context,
location: pathname,
checkFreshAdmission: false,
expectedIdentity: identity.key
}, authority);
if ("error" in result) errors.push(result.error);
} catch (error) {
errors.push(error);
}
try {
await readTransport.close();
transport = void 0;
} catch (error) {
errors.push(error);
}
throwSqliteLifecycleErrors(errors, "Shared-state settlement read and cleanup failed");
authority.assertCurrent();
if (!result || "error" in result || result.value.type !== "userProfiles.reconcile") throw new Error("Unexpected shared-state settlement read reply");
selected.publish(result.value.profile, result.value.emailBindings);
pending = false;
})().finally(() => {
recovery = void 0;
});
const close = () => closing ??= (async () => {
await producer.promise;
await recover();
if (transport) {
await transport.close();
transport = void 0;
}
borrowed?.release();
borrowed = void 0;
selected?.release();
active = false;
unregister();
})().finally(() => {
closing = void 0;
});
const unregister = registerOpenClawStateDatabaseAsyncResource({ async close(target) {
if (!target || target.key === identity.key || target.canonicalPath === identity.canonicalPath) await close();
} });
context.maintenanceScope?.own(producer, "shared-resources", close);
const errors = [];
let result;
try {
result = await operation({
bind(command, settlement, publish, release) {
if (selected || !active) throw new Error("Shared-state settlement read was already bound");
authority.assertCurrent();
selected = {
command: { ...command },
settlement,
publish,
release
};
pending = true;
},
acknowledge(profile, bindings) {
authority.assertCurrent();
if (selected) {
if (!profile || profile.id !== selected.command.profileId) throw new Error("Profile commit differs from its retained settlement read");
selected.publish(profile, bindings);
} else if (profile) throw new Error("Profile commit did not retain its catalog publication");
pending = false;
}
});
} catch (error) {
errors.push(error);
}
let recovered = false;
try {
await recover();
recovered = true;
} catch (error) {
errors.push(error);
} finally {
producer.resolve();
}
if (recovered) try {
await close();
} catch (error) {
errors.push(error);
}
throwSqliteLifecycleErrors(errors, "Shared-state mutation and settlement read failed");
return result;
}
//#endregion
export { withOpenClawStateSettlementRead };