mirror of
https://github.com/stablyai/orca.git
synced 2026-10-22 08:03:37 +00:00
fix(orchestration): restore siblings after uncertain stop
This commit is contained in:
@@ -296,6 +296,28 @@ describe('Task/Dispatch lifecycle guards', () => {
|
||||
expect(database.getDispatchContextById(abandoned.dispatchId)?.status).toBe('failed')
|
||||
})
|
||||
|
||||
it('restores a live sibling after stopping an uncertain worker start', () => {
|
||||
const database = createDatabase()
|
||||
const task = database.createTask({ spec: 'uncertain legacy worker split' })
|
||||
const live = startWorker(database, task.id, 'uncertain_live')
|
||||
sqliteFor(database).prepare("UPDATE tasks SET status = 'ready' WHERE id = ?").run(task.id)
|
||||
const uncertain = database.createStartingWorkerDispatch({ taskId: task.id, startOptions: {} })
|
||||
database.markWorkerStartUnknown(uncertain.dispatch.id, 'agent_readiness', 'outcome unknown')
|
||||
expect(database.getTask(task.id)?.status).toBe('blocked')
|
||||
|
||||
expect(database.beginWorkerStop(uncertain.dispatch.id).disposition).toBe('stopping')
|
||||
expect(database.settleWorkerStop(uncertain.dispatch.id).state).toBe('stopped')
|
||||
expect(database.getTask(task.id)?.status).toBe('dispatched')
|
||||
expect(
|
||||
database.settleWorkerReport({
|
||||
taskId: task.id,
|
||||
dispatchId: live.dispatchId,
|
||||
outcome: 'succeeded',
|
||||
result: 'live sibling completed'
|
||||
})
|
||||
).toEqual({ action: 'settled', outcome: 'succeeded', duplicate: false })
|
||||
})
|
||||
|
||||
it('rejects gate creation while a supervised worker remains active', () => {
|
||||
const database = createDatabase()
|
||||
const task = database.createTask({ spec: 'worker gate guard' })
|
||||
|
||||
@@ -6418,7 +6418,7 @@ export class OrchestrationDb {
|
||||
WHERE id = ?`
|
||||
)
|
||||
.run(dispatchId)
|
||||
this.blockTaskWithoutActiveSibling(dispatch.task_id, dispatchId)
|
||||
this.reconcileTaskAfterDispatchInterruption(dispatch.task_id, dispatchId)
|
||||
this.closeQuestionsForDispatch(dispatchId)
|
||||
this.db.exec('COMMIT')
|
||||
return {
|
||||
@@ -6454,7 +6454,7 @@ export class OrchestrationDb {
|
||||
WHERE id = ? AND status IN ('pending', 'dispatched')`
|
||||
)
|
||||
.run(dispatchId)
|
||||
this.blockTaskWithoutActiveSibling(dispatch.task_id, dispatchId)
|
||||
this.reconcileTaskAfterDispatchInterruption(dispatch.task_id, dispatchId)
|
||||
this.db.exec('COMMIT')
|
||||
return this.getWorkerDispatch(dispatchId) as WorkerDispatchRow
|
||||
} catch (error) {
|
||||
@@ -6500,7 +6500,7 @@ export class OrchestrationDb {
|
||||
WHERE id = ? AND status IN ('pending', 'dispatched')`
|
||||
)
|
||||
.run(dispatchId)
|
||||
this.blockTaskWithoutActiveSibling(dispatch.task_id, dispatchId)
|
||||
this.reconcileTaskAfterDispatchInterruption(dispatch.task_id, dispatchId)
|
||||
this.db.exec('COMMIT')
|
||||
return this.getWorkerDispatch(dispatchId) as WorkerDispatchRow
|
||||
} catch (error) {
|
||||
@@ -6598,7 +6598,7 @@ export class OrchestrationDb {
|
||||
WHERE id = ?`
|
||||
)
|
||||
.run(dispatchId)
|
||||
this.blockTaskWithoutActiveSibling(dispatch.task_id, dispatchId)
|
||||
this.reconcileTaskAfterDispatchInterruption(dispatch.task_id, dispatchId)
|
||||
this.closeQuestionsForDispatch(dispatchId)
|
||||
this.db.exec('COMMIT')
|
||||
return {
|
||||
@@ -7330,16 +7330,17 @@ export class OrchestrationDb {
|
||||
.get(taskId) as DispatchContextRow | undefined
|
||||
}
|
||||
|
||||
private blockTaskWithoutActiveSibling(taskId: string, dispatchId: string): void {
|
||||
private reconcileTaskAfterDispatchInterruption(taskId: string, dispatchId: string): void {
|
||||
this.db
|
||||
.prepare(
|
||||
`UPDATE tasks SET status = 'blocked'
|
||||
WHERE id = ? AND NOT EXISTS (
|
||||
`UPDATE tasks
|
||||
SET status = CASE WHEN EXISTS (
|
||||
SELECT 1 FROM dispatch_contexts
|
||||
WHERE task_id = tasks.id AND id != ? AND status IN ('pending', 'dispatched')
|
||||
)`
|
||||
) THEN 'dispatched' ELSE 'blocked' END
|
||||
WHERE id = ? AND status IN ('dispatched', 'blocked')`
|
||||
)
|
||||
.run(taskId, dispatchId)
|
||||
.run(dispatchId, taskId)
|
||||
}
|
||||
|
||||
getDispatchContextById(dispatchId: string): DispatchContextRow | undefined {
|
||||
|
||||
Reference in New Issue
Block a user