fix(worker): claim workspace lock in main before enqueue (D-02)

The lock was previously claimed when the worker reported `running`, which
is after `agent.prompt` had already started streaming. Two concurrent
runs targeting the same workspace could both pass the main-side checks,
both get enqueued, and both read half-written state before one of them
lost the lock race and was cancelled mid-flight.

Move the `claimWorkspaceLock` call into `dispatchRunToWorker` so main
coordinates exclusivity authoritatively. If the lock is unavailable,
the run is finished as failed and never enqueued. The worker-side
lease-renewal path is preserved since it is a lease, not a lock.
This commit is contained in:
ZacharyZhang-NY committed 2026-04-16 21:49:30 -04:00
1 parent f86b3ddbac
commit ff0c01fe87
2 files changed
+27 -4

No files matched your search

+3 -4
View File
@@ -110,12 +110,11 @@ export async function handleWorkerMessage(
});
}
if (event.status === "running") {
// D-02: Workspace lock is claimed authoritatively in main's
// dispatchRunToWorker before enqueue. Only lease renewal and
// run-started housekeeping run here.
try {
const run = db.getRun(event.runId);
if (run.workspaceId && !db.claimWorkspaceLock(run.workspaceId, run.id)) {
logger.error(`[workspace] Failed to claim lock for workspace ${run.workspaceId} when run ${run.id} entered running state. Cancelling run.`);
worker?.postMessage({ type: "cancel-run", runId: run.id });
}
db.renewTaskLease(run.taskId, run.id);
onRunStarted?.(run.id, run.taskId, run.agentId, run.companyId);
} catch {