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:
1 parent
02e87dc06d
commit
08935b3379
5 files changed
+326
-71
No files matched your search
+24
-16
@@ -164,7 +164,7 @@ describe("AppDatabase", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("atomically checks out unclaimed work to a single agent", () => {
|
||||
it("atomically checks out unclaimed work via CAS with run ID", () => {
|
||||
const companyId = db.saveCompany({
|
||||
name: "Checkout Company",
|
||||
description: "Atomic checkout validation",
|
||||
@@ -191,18 +191,12 @@ describe("AppDatabase", () => {
|
||||
capabilities: "Leads",
|
||||
budgetMonthlyUsd: 100,
|
||||
});
|
||||
const contributorId = db.saveAgent({
|
||||
companyId,
|
||||
name: "Contributor",
|
||||
role: "IC",
|
||||
title: "Contributor",
|
||||
status: "active",
|
||||
reportsTo: leadId,
|
||||
connectorId: "codex_local",
|
||||
workspaceId,
|
||||
model: null,
|
||||
capabilities: "Executes",
|
||||
budgetMonthlyUsd: 100,
|
||||
db.saveConnector({
|
||||
id: "codex_local",
|
||||
command: "codex",
|
||||
model: "gpt-5",
|
||||
envBindingText: "",
|
||||
notes: "Test connector",
|
||||
});
|
||||
const taskId = db.saveTask({
|
||||
companyId,
|
||||
@@ -214,11 +208,25 @@ describe("AppDatabase", () => {
|
||||
status: "todo",
|
||||
});
|
||||
|
||||
expect(db.checkoutTask(taskId, leadId)).toBe(true);
|
||||
expect(db.checkoutTask(taskId, contributorId)).toBe(false);
|
||||
const { id: runId1 } = db.createRun({
|
||||
companyId,
|
||||
taskId,
|
||||
agentId: leadId,
|
||||
workspaceId,
|
||||
connectorId: "codex_local",
|
||||
});
|
||||
const { id: runId2 } = db.createRun({
|
||||
companyId,
|
||||
taskId,
|
||||
agentId: leadId,
|
||||
workspaceId,
|
||||
connectorId: "codex_local",
|
||||
});
|
||||
|
||||
expect(db.checkoutTask(taskId, runId1)).toBe(true);
|
||||
expect(db.checkoutTask(taskId, runId2)).toBe(false);
|
||||
|
||||
const task = db.getTask(taskId);
|
||||
expect(task.assigneeAgentId).toBe(leadId);
|
||||
expect(task.status).toBe("in_progress");
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user