openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
552 lines (551 loc) • 28.1 kB
JavaScript
import { a as executeSqliteQueryTakeFirstSync, d as sqliteStringSet, i as executeSqliteQuerySync, o as getNodeSqliteKysely } from "./kysely-sync-DUWzQvCU.mjs";
import { b as extractSqliteTableSchema, i as getAdmittedSqliteSchemaFacts } from "./sqlite-schema-facts-BVf0E_0z.mjs";
import { i as tableExists, n as ensureColumn } from "./openclaw-state-db-schema-helpers-DKz5xGgh.mjs";
import { r as runSqliteDeferredTransactionSync } from "./sqlite-transaction-DBRLvCDM.mjs";
import { r as parseSqliteTableDefinition } from "./sqlite-schema-contract-assembly-DHmv6TIa.mjs";
import { i as sessionChanges } from "./session-row-changes-Dj2yVWo-.mjs";
import { t as OPENCLAW_STATE_SCHEMA_SQL } from "./openclaw-state-schema-Cr2v_hbj.mjs";
import { i as generateSecureToken } from "./secure-random-B2AO8OrW.mjs";
import "./worker-protocol-primitives-ulaCa2Ea.mjs";
import { a as isForceAbandonedWorkerPlacement, h as required, i as isCurrentPlacementTurnClaim, r as assertRecordShape, s as normalizeEpoch } from "./placement-record-BZ5ExJ2S.mjs";
import { M as matchesWorkspaceResultClaim, a as query, c as revivePlacementProjectionInteger, d as turnClaimValues, i as getRequired, j as isWorkerWorkspaceResultReconciling, l as selectWorkerPlacementRows, n as find, r as fromRow, u as transitionValues, x as publishPlacementTurnClaimState } from "./placement-row-codec-Cpn-JKmv.mjs";
import { r as isCurrentJournalOwner, t as clearWorkerWorkspaceReconciliation } from "./placement-workspace-journal-D1i7Bc34.mjs";
import { l as pendingResultFromRow, o as hasWorkerWorkspacePendingResult } from "./placement-workspace-result-DabzjaLS.mjs";
import { t as boundedWorkerError } from "./worker-error-Db8qkNbb.mjs";
import { a as jsonArrayFrom, o as jsonObjectFrom } from "./placement-workspace-reservation.kernel-BwT507ly.mjs";
import { t as workerInferenceMetadata } from "./inference-placement-C1SOuYae.mjs";
import { t as decodeWorkerEnvironmentRow } from "./store-row-codec-l38X6-mv.mjs";
import { isDeepStrictEqual } from "node:util";
//#region src/gateway/worker-environments/placement-drain.ts
function drainWorkerSessionPlacement(db, input, nowMs) {
const sessionId = required(input.sessionId, "session id");
const environmentId = required(input.environmentId, "environment id");
const ownerEpoch = normalizeEpoch(input.ownerEpoch, "active owner epoch");
const current = getRequired(db, sessionId);
if (current.state !== "active" || current.generation !== input.expectedGeneration || current.environmentId !== environmentId || current.activeOwnerEpoch !== ownerEpoch) throw new Error(`Cannot drain stale worker placement for session ${sessionId}`);
if (input.expectedUpdatedAtMs !== void 0 && current.updatedAtMs !== input.expectedUpdatedAtMs) throw new Error(`Cannot drain changed worker placement activity for session ${sessionId}`);
if (!input.allowPendingWorkspaceResult && hasWorkerWorkspacePendingResult(db, sessionId)) throw new Error(`Cannot drain session ${sessionId} with a pending cloud workspace result`);
if (input.requireUnclaimed && current.turnClaim) throw new Error(`Cannot drain session ${sessionId} during an active turn`);
if (input.expectedTurnClaim && !isCurrentPlacementTurnClaim(current, input.expectedTurnClaim)) throw new Error(`Cannot drain stale worker turn for session ${sessionId}`);
const values = transitionValues(current, "draining", input.workspaceBaseManifestRef === void 0 ? {} : { workspaceBaseManifestRef: input.workspaceBaseManifestRef }, nowMs);
Object.assign(values, turnClaimValues(current.turnClaim));
assertRecordShape({
...current,
state: "draining",
workspaceBaseManifestRef: values.workspace_base_manifest_ref
});
if (executeSqliteQuerySync(db, query(db).updateTable("worker_session_placements").set(values).where("session_id", "=", sessionId).where("state", "=", "active").where("transition_generation", "=", current.generation).where("environment_id", "=", environmentId).where("active_owner_epoch", "=", ownerEpoch)).numAffectedRows !== 1n) throw new Error(`Worker session placement ${sessionId} changed during drain`);
if (input.workspaceBaseManifestRef !== void 0) {
clearWorkerWorkspaceReconciliation(db, sessionId, input.workspaceBaseManifestRef);
sessionChanges.emit({
agentId: current.agentId,
sessionKey: current.sessionKey
}, db);
}
const record = getRequired(db, sessionId);
publishPlacementTurnClaimState(db, record);
return record;
}
//#endregion
//#region src/gateway/worker-environments/placement-move-intent.ts
const MOVE_OPERATION_PREFIX = "move:v1:";
const MOVE_MACHINE_CLASS_MAX_LENGTH = 128;
const MOVE_OS_MAX_LENGTH = 64;
const moveQuery = (db) => getNodeSqliteKysely(db);
const ensuredMoveSchemaHandles = /* @__PURE__ */ new WeakSet();
function ensureWorkerPlacementMoveSchema(db) {
if (ensuredMoveSchemaHandles.has(db)) return;
db.exec(extractSqliteTableSchema(OPENCLAW_STATE_SCHEMA_SQL, "worker_session_placement_moves", { errorMessage: "Worker placement move schema marker is missing" }));
ensureColumn(db, "worker_session_placement_moves", "target_machine_class TEXT");
ensureColumn(db, "worker_session_placement_moves", "target_os TEXT");
ensureColumn(db, "worker_session_placement_moves", "abandon_source INTEGER");
ensuredMoveSchemaHandles.add(db);
}
function ensureExistingWorkerPlacementMoveSchema(db) {
if (ensuredMoveSchemaHandles.has(db)) return true;
if (!tableExists(db, "worker_session_placement_moves")) return false;
ensureWorkerPlacementMoveSchema(db);
return true;
}
function normalizeGeneration(value) {
if (!Number.isSafeInteger(value) || value < 0) throw new Error("Worker placement move source generation must be a non-negative integer");
return value;
}
function boundedIdentifier(value, field, maximumLength = 256) {
const normalized = required(value, field);
if (normalized.length > maximumLength) throw new Error(`Worker session placement ${field} exceeds ${maximumLength} characters`);
return normalized;
}
function normalizeOperationId(value) {
const operationId = required(value, "move operation id");
if (!operationId.startsWith(MOVE_OPERATION_PREFIX) || operationId.length > 128) throw new Error("Worker session placement move operation id is invalid");
return operationId;
}
function normalizeWorkerPlacementMoveTarget(target) {
if (target.kind !== "profile" && Object.hasOwn(target, "os")) throw new Error("Worker placement move operating system requires a profile target");
switch (target.kind) {
case "gateway": return { kind: "gateway" };
case "profile": {
const machineClass = target.machineClass;
return {
kind: "profile",
profileId: boundedIdentifier(target.profileId, "move profile id"),
...target.os === void 0 ? {} : { os: boundedIdentifier(target.os, "move operating system", MOVE_OS_MAX_LENGTH) },
...machineClass === void 0 ? {} : { machineClass: boundedIdentifier(machineClass, "move machine class", MOVE_MACHINE_CLASS_MAX_LENGTH) }
};
}
case "device": return {
kind: "device",
deviceId: boundedIdentifier(target.deviceId, "move device id")
};
}
throw new Error("Worker placement move target is invalid");
}
function normalizeWorkerPlacementMoveSource(source) {
return {
generation: normalizeGeneration(source.generation),
environmentId: boundedIdentifier(source.environmentId, "move source environment id"),
ownerEpoch: normalizeEpoch(source.ownerEpoch, "move source owner epoch")
};
}
function targetValues(target) {
return {
target_kind: target.kind,
target_id: target.kind === "profile" ? target.profileId : target.kind === "device" ? target.deviceId : null,
target_machine_class: target.kind === "profile" ? target.machineClass ?? null : null,
target_os: target.kind === "profile" ? target.os ?? null : null
};
}
function normalizeAbandonSource(value) {
if (value === null) return false;
if (value === 1) return true;
throw new Error("Invalid worker placement move source abandonment value");
}
function workerPlacementMoveFromRow(row) {
const source = normalizeWorkerPlacementMoveSource({
generation: row.source_generation,
environmentId: row.source_environment_id,
ownerEpoch: row.source_owner_epoch
});
let target;
if (row.target_kind !== "profile" && (row.target_machine_class !== null || row.target_os !== null)) throw new Error(`Invalid worker placement move target: ${row.target_kind}`);
if (row.target_kind === "gateway" && row.target_id === null) target = { kind: "gateway" };
else if (row.target_kind === "profile" && row.target_id !== null) target = normalizeWorkerPlacementMoveTarget({
kind: "profile",
profileId: row.target_id,
...row.target_os === null ? {} : { os: row.target_os },
...row.target_machine_class === null ? {} : { machineClass: row.target_machine_class }
});
else if (row.target_kind === "device" && row.target_id !== null) target = {
kind: "device",
deviceId: boundedIdentifier(row.target_id, "move device id")
};
else throw new Error(`Invalid worker placement move target: ${row.target_kind}`);
const abandonSource = normalizeAbandonSource(row.abandon_source);
if (abandonSource && target.kind !== "gateway") throw new Error("Worker placement move source abandonment requires a Gateway target");
return {
operationId: normalizeOperationId(row.operation_id),
sessionId: required(row.session_id, "move session id"),
source,
target,
abandonSource,
lastError: row.last_error,
createdAtMs: row.created_at_ms,
updatedAtMs: row.updated_at_ms
};
}
function findMoveRow(db, column, value) {
if (!ensureExistingWorkerPlacementMoveSchema(db)) return;
return executeSqliteQueryTakeFirstSync(db, moveQuery(db).selectFrom("worker_session_placement_moves").selectAll().where(column, "=", value));
}
/** Display reads tolerate the shipped additive columns without mutating their source. */
function readWorkerPlacementMovesReadOnly(db, sessionIds) {
const results = /* @__PURE__ */ new Map();
if (!tableExists(db, "worker_session_placement_moves")) return results;
for (let offset = 0; offset < sessionIds.length; offset += 250) for (const row of executeSqliteQuerySync(db, moveQuery(db).selectFrom("worker_session_placement_moves").selectAll().where("session_id", "in", sessionIds.slice(offset, offset + 250))).rows) {
const intent = workerPlacementMoveFromRow({
...row,
target_machine_class: row.target_machine_class ?? null,
target_os: row.target_os ?? null,
abandon_source: row.abandon_source ?? null
});
results.set(intent.sessionId, intent);
}
return results;
}
function requireExactMove(db, input) {
const operationId = normalizeOperationId(input.operationId);
const sessionId = required(input.sessionId, "move session id");
const row = findMoveRow(db, "operation_id", operationId);
if (!row || row.session_id !== sessionId) throw new Error(`Session ${sessionId} placement move changed before completion`);
return workerPlacementMoveFromRow(row);
}
function exactMoveValues(intent) {
return {
operation_id: intent.operationId,
session_id: intent.sessionId,
source_generation: intent.source.generation,
source_environment_id: intent.source.environmentId,
source_owner_epoch: intent.source.ownerEpoch,
...targetValues(intent.target),
abandon_source: intent.abandonSource ? 1 : null
};
}
function deleteExactMove(db, intent) {
const statement = moveQuery(db).deleteFrom("worker_session_placement_moves").where((eb) => eb.and(exactMoveValues(intent)));
if (executeSqliteQuerySync(db, statement).numAffectedRows !== 1n) throw new Error(`Session ${intent.sessionId} placement move changed before completion`);
sessionChanges.emit({
all: true,
scope: "worker-placements"
}, db);
}
function requireExactAttachedEnvironment(db, input) {
const row = executeSqliteQueryTakeFirstSync(db, moveQuery(db).selectFrom("worker_environments").select([
"state",
"owner_epoch",
"profile_id",
"attached_session_ids_json"
]).where("environment_id", "=", input.environmentId));
let attachedSessionIds;
try {
attachedSessionIds = row ? JSON.parse(row.attached_session_ids_json) : void 0;
} catch {
attachedSessionIds = void 0;
}
if (!row || row.state !== "attached" || row.owner_epoch !== input.ownerEpoch || input.profileId !== void 0 && row.profile_id !== input.profileId || !Array.isArray(attachedSessionIds) || attachedSessionIds.length !== 1 || attachedSessionIds[0] !== input.sessionId) throw new Error(`Cannot move stale worker environment for session ${input.sessionId}`);
}
function createPlacementMoveOps(runtime) {
const { read, write, now } = runtime;
const completeSourceToLocal = (completion) => write((db) => {
const { state, input } = completion;
const intent = requireExactMove(db, input);
if (state === "failed" && (!intent.abandonSource || intent.target.kind !== "gateway")) throw new Error(`Session ${intent.sessionId} placement move is not an abandonment`);
const current = getRequired(db, intent.sessionId);
const label = state === "failed" ? "abandoned" : "Gateway";
if (current.state !== state || current.generation !== input.expectedGeneration || current.environmentId !== intent.source.environmentId || current.activeOwnerEpoch !== intent.source.ownerEpoch || state === "failed" && (current.recoveryError !== input.expectedRecoveryError || current.turnClaim !== null)) throw new Error(`Cannot complete stale ${label} placement move for session ${intent.sessionId}`);
const values = transitionValues(current, "local", {}, now());
let statement = query(db).updateTable("worker_session_placements").set(values).where("session_id", "=", intent.sessionId).where("state", "=", state).where("transition_generation", "=", current.generation).where("environment_id", "=", intent.source.environmentId).where("active_owner_epoch", "=", intent.source.ownerEpoch);
if (state === "failed") statement = statement.where("recovery_error", "=", input.expectedRecoveryError);
if (executeSqliteQuerySync(db, statement.where("turn_claim_owner", "is", null)).numAffectedRows !== 1n) throw new Error(`Session ${intent.sessionId} changed during ${label} placement move`);
if (intent.target.kind === "gateway") deleteExactMove(db, intent);
const record = getRequired(db, intent.sessionId);
publishPlacementTurnClaimState(db, record);
return {
placement: record,
moveRemoved: intent.target.kind === "gateway"
};
});
return {
getPlacementMove(sessionId) {
const row = findMoveRow(read(), "session_id", required(sessionId, "move session id"));
return row ? workerPlacementMoveFromRow(row) : void 0;
},
beginPlacementMove(input, beforeBegin) {
const sessionId = required(input.sessionId, "move session id");
const source = normalizeWorkerPlacementMoveSource(input.source);
const target = normalizeWorkerPlacementMoveTarget(input.target);
const abandonSource = input.abandonSource === true;
if (abandonSource && target.kind !== "gateway") throw new Error("Worker placement move source abandonment requires a Gateway target");
const operationId = `${MOVE_OPERATION_PREFIX}${generateSecureToken(32)}`;
return write((db) => {
const existingRow = findMoveRow(db, "session_id", sessionId);
if (existingRow) {
const existing = workerPlacementMoveFromRow(existingRow);
if (!isDeepStrictEqual(existing.source, source) || !isDeepStrictEqual(existing.target, target) || existing.abandonSource !== abandonSource) throw new Error(`Session ${sessionId} already has a conflicting placement move`);
const placement = getRequired(db, sessionId);
beforeBegin?.(placement, true);
return {
intent: existing,
placement,
joined: true
};
}
const current = getRequired(db, sessionId);
if (current.state !== "active" && !(abandonSource && isForceAbandonedWorkerPlacement(current)) || current.generation !== source.generation || current.environmentId !== source.environmentId || current.activeOwnerEpoch !== source.ownerEpoch) throw new Error(`Cannot move stale worker placement for session ${sessionId}`);
if (current.state === "active") requireExactAttachedEnvironment(db, {
sessionId,
...source
});
beforeBegin?.(current, false);
ensureWorkerPlacementMoveSchema(db);
const timestamp = now();
const row = {
operation_id: operationId,
session_id: sessionId,
source_generation: source.generation,
source_environment_id: source.environmentId,
source_owner_epoch: source.ownerEpoch,
...targetValues(target),
abandon_source: abandonSource ? 1 : null,
last_error: null,
created_at_ms: timestamp,
updated_at_ms: timestamp
};
executeSqliteQuerySync(db, moveQuery(db).insertInto("worker_session_placement_moves").values(row));
const placement = current.state === "failed" ? current : drainWorkerSessionPlacement(db, {
sessionId,
...source,
expectedGeneration: source.generation,
...abandonSource ? { allowPendingWorkspaceResult: true } : {}
}, timestamp);
return {
intent: workerPlacementMoveFromRow(row),
placement,
joined: false
};
});
},
recordPlacementMoveError(input) {
return write((db) => {
const row = findMoveRow(db, "operation_id", normalizeOperationId(input.operationId));
if (!row || row.session_id !== required(input.sessionId, "move session id")) return false;
const intent = workerPlacementMoveFromRow(row);
const statement = moveQuery(db).updateTable("worker_session_placement_moves").set({
last_error: boundedWorkerError(input.error),
updated_at_ms: now()
}).where((eb) => eb.and(exactMoveValues(intent)));
sessionChanges.emit({
all: true,
scope: "worker-placements"
}, db);
return executeSqliteQuerySync(db, statement).numAffectedRows === 1n;
});
},
cancelPlacementMove(input) {
return write((db) => {
if (input.expectedLocalGeneration !== void 0) {
const current = find(db, required(input.sessionId, "move session id"));
if (current?.state !== "local" || current.generation !== input.expectedLocalGeneration) return false;
}
deleteExactMove(db, requireExactMove(db, input));
return true;
});
},
completePlacementMoveSourceToLocal(input) {
return completeSourceToLocal({
state: "reconciling",
input
});
},
completeAbandonedPlacementMoveSourceToLocal(input) {
return completeSourceToLocal({
state: "failed",
input
});
},
completePlacementMoveToWorker(input) {
const environmentId = boundedIdentifier(input.environmentId, "move destination environment id");
const ownerEpoch = normalizeEpoch(input.ownerEpoch, "move destination owner epoch");
return write((db) => {
const intent = requireExactMove(db, input);
if (intent.target.kind === "gateway") throw new Error(`Session ${intent.sessionId} placement move target is not a worker`);
const current = getRequired(db, intent.sessionId);
if (current.state !== "active" || current.generation !== input.expectedGeneration || current.environmentId !== environmentId || current.activeOwnerEpoch !== ownerEpoch) throw new Error(`Cannot complete stale worker placement move for session ${intent.sessionId}`);
const profileId = intent.target.kind === "profile" ? intent.target.profileId : `device:${intent.target.deviceId}`;
requireExactAttachedEnvironment(db, {
sessionId: intent.sessionId,
environmentId,
ownerEpoch,
profileId
});
deleteExactMove(db, intent);
return current;
});
}
};
}
//#endregion
//#region src/gateway/worker-environments/placement-read-projection.ts
const projectionSchemas = /* @__PURE__ */ new WeakMap();
const PROJECTION_BATCH_SIZE = 250;
function readProjectionSchema(db) {
const schema = getAdmittedSqliteSchemaFacts(db);
if (!schema) throw new Error("Worker placement projection requires admitted schema facts");
let projectionSchema = projectionSchemas.get(schema);
if (!projectionSchema) {
const pendingColumns = parseSqliteTableDefinition(schema.tableSql.get("worker_workspace_pending_results") ?? null, "worker_workspace_pending_results").columns;
const moveSql = schema.tableSql.get("worker_session_placement_moves");
const moveColumns = moveSql ? parseSqliteTableDefinition(moveSql, "worker_session_placement_moves").columns : void 0;
projectionSchema = {
repositoryWorkspace: pendingColumns.has("repository_workspace_id"),
...moveColumns ? { moves: {
machineClass: moveColumns.has("target_machine_class"),
os: moveColumns.has("target_os"),
abandonSource: moveColumns.has("abandon_source")
} } : {}
};
projectionSchemas.set(schema, projectionSchema);
}
return projectionSchema;
}
function moveRows(db, sessionIds, schema) {
return getNodeSqliteKysely(db).selectFrom("worker_session_placement_moves").select([
"operation_id",
"session_id",
"source_generation",
"source_environment_id",
"source_owner_epoch",
"target_kind",
"target_id",
"last_error",
"created_at_ms",
"updated_at_ms"
]).select((eb) => [
(schema.moves?.machineClass ? eb.ref("target_machine_class") : eb.val(null)).as("target_machine_class"),
(schema.moves?.os ? eb.ref("target_os") : eb.val(null)).as("target_os"),
(schema.moves?.abandonSource ? eb.ref("abandon_source") : eb.val(null)).as("abandon_source")
]).where("session_id", "in", sqliteStringSet(sessionIds)).$assertType();
}
function readWorkerPlacementMoveAuthorityInDatabase(db, sessionId) {
const schema = readProjectionSchema(db);
const query = getNodeSqliteKysely(db);
const row = executeSqliteQuerySync(db, query.selectNoFrom((eb) => [jsonObjectFrom(selectWorkerPlacementRows(db, [sessionId])).$castTo().as("placement"), schema.moves ? jsonObjectFrom(moveRows(db, [sessionId], schema)).$castTo().as("move") : eb.val(null).as("move")])).rows[0];
return {
placement: row.placement === null ? void 0 : fromRow(JSON.parse(row.placement, revivePlacementProjectionInteger)),
move: row.move === null ? void 0 : workerPlacementMoveFromRow(JSON.parse(row.move, revivePlacementProjectionInteger))
};
}
function readProjectionRows(db, sessionIds, schema) {
const query = getNodeSqliteKysely(db);
const ids = sqliteStringSet(sessionIds);
const placements = selectWorkerPlacementRows(db, sessionIds);
const pendingResults = query.selectFrom("worker_workspace_pending_results").select([
"session_id",
"environment_id",
"owner_epoch",
"placement_generation",
"claim_id",
"run_id",
"gateway_instance_id",
"recovery_requested_at_ms",
"workspace_accepted_at_ms",
"staged_result_ref",
"created_at_ms"
]).select((eb) => (schema.repositoryWorkspace ? eb.ref("repository_workspace_id") : eb.val(null)).as("repository_workspace_id")).where("session_id", "in", ids).$assertType();
const journals = query.selectFrom("worker_workspace_reconciliations").select([
"session_id",
"environment_id",
"owner_epoch",
"placement_generation"
]).where("session_id", "in", ids);
const moves = moveRows(db, sessionIds, schema);
const environments = query.selectFrom("worker_environments").select([
"environment_id",
"provider_id",
"profile_id",
"profile_snapshot_json",
"preparation_consumed_at_ms",
"preparation_demand_at_ms",
"preparation_expires_at_ms",
"preparation_key",
"preparation_purpose",
"provision_operation_id",
"node_setup_id",
"node_device_id",
"shared_host",
"lease_id",
"ssh_host",
"ssh_port",
"ssh_user",
"ssh_host_key",
"ssh_key_ref_json",
"desktop_json",
"bootstrap_bundle_hash",
"bootstrap_openclaw_version",
"bootstrap_protocol_features_json",
"bootstrap_install_kind",
"owner_epoch",
"teardown_terminal_state",
"state",
"attached_session_ids_json",
"created_at_ms",
"updated_at_ms",
"state_changed_at_ms",
"last_activated_at_ms",
"idle_since_at_ms",
"destroy_requested_at_ms",
"last_error"
]).where("environment_id", "in", query.selectFrom("worker_session_placements").select("environment_id").where("session_id", "in", ids).where("environment_id", "is not", null)).$assertType();
return executeSqliteQuerySync(db, query.selectNoFrom((eb) => [
jsonArrayFrom(placements).$castTo().as("placements"),
jsonArrayFrom(pendingResults).$castTo().as("pendingResults"),
jsonArrayFrom(journals).$castTo().as("journals"),
schema.moves ? jsonArrayFrom(moves).$castTo().as("moves") : eb.val("[]").as("moves"),
jsonArrayFrom(environments).$castTo().as("environments")
])).rows[0];
}
function readWorkerSessionPlacementProjectionInDatabase(db, sessionIds, conflictBindings) {
const read = () => {
const schema = readProjectionSchema(db);
const placements = /* @__PURE__ */ new Map();
const moves = /* @__PURE__ */ new Map();
const pendingResults = /* @__PURE__ */ new Map();
const reconcilingSessionIds = /* @__PURE__ */ new Set();
const workspaceRecoveryPendingSessionIds = /* @__PURE__ */ new Set();
const workspaceJournalOwnerSessionIds = /* @__PURE__ */ new Set();
const environments = /* @__PURE__ */ new Map();
for (let offset = 0; offset < sessionIds.length; offset += PROJECTION_BATCH_SIZE) {
const rows = readProjectionRows(db, sessionIds.slice(offset, offset + PROJECTION_BATCH_SIZE), schema);
for (const row of JSON.parse(rows.placements, revivePlacementProjectionInteger)) {
const placement = fromRow(row);
placements.set(placement.sessionId, placement);
}
for (const row of JSON.parse(rows.pendingResults, revivePlacementProjectionInteger)) {
const pending = pendingResultFromRow(row);
pendingResults.set(pending.sessionId, pending);
workspaceRecoveryPendingSessionIds.add(pending.sessionId);
if (isWorkerWorkspaceResultReconciling(placements.get(pending.sessionId), pending)) reconcilingSessionIds.add(pending.sessionId);
}
for (const row of JSON.parse(rows.journals, revivePlacementProjectionInteger)) {
workspaceRecoveryPendingSessionIds.add(row.session_id);
if (isCurrentJournalOwner(db, placements.get(row.session_id), {
sessionId: row.session_id,
environmentId: row.environment_id,
ownerEpoch: row.owner_epoch,
placementGeneration: row.placement_generation
}, pendingResults)) workspaceJournalOwnerSessionIds.add(row.session_id);
}
for (const row of JSON.parse(rows.moves, revivePlacementProjectionInteger)) {
const move = workerPlacementMoveFromRow(row);
moves.set(move.sessionId, move);
}
for (const row of JSON.parse(rows.environments, revivePlacementProjectionInteger)) {
const record = decodeWorkerEnvironmentRow(row, []);
environments.set(record.environmentId, {
environmentId: record.environmentId,
providerId: record.providerId,
profileId: record.profileId,
profileSnapshot: record.profileSnapshot,
...workerInferenceMetadata(record),
state: record.state,
leaseId: record.leaseId,
ownerEpoch: record.ownerEpoch,
nodeDeviceId: record.nodeDeviceId,
attachedSessionIds: record.attachedSessionIds
});
}
}
const projection = {
placements,
moves,
pendingResults,
workspaceJournalOwnerSessionIds,
workspaceResultReconcilingSessionIds: reconcilingSessionIds,
workspaceRecoveryPendingSessionIds,
environments
};
const conflictSessionIds = /* @__PURE__ */ new Set();
for (const binding of conflictBindings) {
const record = placements.get(binding.placement.sessionId);
const pending = pendingResults.get(binding.placement.sessionId);
if (record && record.environmentId === binding.placement.environmentId && record.activeOwnerEpoch === binding.placement.activeOwnerEpoch && (record.generation === binding.placement.generation || pending && matchesWorkspaceResultClaim(record, pending, binding.claim))) conflictSessionIds.add(record.sessionId);
}
return {
projection,
conflictSessionIds
};
};
return sessionIds.length <= PROJECTION_BATCH_SIZE ? read() : runSqliteDeferredTransactionSync(db, read);
}
//#endregion
export { drainWorkerSessionPlacement as a, readWorkerPlacementMovesReadOnly as i, readWorkerSessionPlacementProjectionInDatabase as n, createPlacementMoveOps as r, readWorkerPlacementMoveAuthorityInDatabase as t };