feat(04-01): implement CAS checkout, lock release, stale recovery, and migration 16

- Rewrite checkoutTask to use runId-based CAS with checkout_run_id IS NULL guard
- Add releaseTaskLock and recoverStaleLocks methods
- Add lock release in finishRun and cancelRunForDeletion exit paths
- Add migration 16: pending_wakes to wakeup_requests cutover with DROP TABLE
- Replace all pending_wakes references with wakeup_requests
- Add wakeup lifecycle CRUD: enqueue, claim, complete, defer, promote, list
- Update api-server, orchestration-service, worker-service callers
- Update existing database.test.ts for new checkoutTask signature
This commit is contained in:
ZacharyZhang-NY committed 2026-03-26 18:56:54 -04:00
1 parent 02e87dc06d
commit 08935b3379
5 files changed
+326 -71

No files matched your search

+4 -4
View File
@@ -473,7 +473,7 @@ export function createOrchestrationService({
const agentBusy = hasActiveRun({ agentId, companyId });
const runId = startAgentHeartbeatRun(agentId, companyId, trigger);
if (!runId && agentBusy) {
db.enqueuePendingWake(companyId, agentId, trigger);
db.enqueueWakeupRequest(companyId, agentId, trigger, trigger);
}
return runId;
}
@@ -689,9 +689,9 @@ export function createOrchestrationService({
logger.info(`[heartbeat] Released ${staleReleased} stale workspace lock(s)`);
publishDomainChanged();
}
const stalePendingWakes = db.purgeExpiredPendingWakes();
if (stalePendingWakes > 0) {
logger.info(`[heartbeat] Purged ${stalePendingWakes} stale pending wake(s)`);
const staleWakeups = db.purgeExpiredWakeupRequests();
if (staleWakeups > 0) {
logger.info(`[heartbeat] Purged ${staleWakeups} expired wakeup request(s)`);
}
} catch (error) {
logger.error(`[heartbeat] Stale lock cleanup failed: ${error instanceof Error ? error.message : String(error)}`);