fix(orchestration): credit worker exit during stop inspection

This commit is contained in:
Jinwoo-H
2026-09-05 00:40:46 -04:00
parent 53a4209334
commit 26ff7ea00a
2 changed files with 24 additions and 0 deletions
@@ -58,6 +58,20 @@ describe('a worker whose process exits while its own stop is in flight', () => {
expect(receipt.state).toBe('stopped')
})
it('accepts an exit observed while inspecting the process before close', async () => {
const { dispatchId } = await h.startWorker()
vi.mocked(h.runtime.showTerminal).mockImplementation(async (handle) => {
fireExit(handle)
return { handle, connected: false } as never
})
vi.spyOn(h.runtime, 'getTerminalLivenessVerdict').mockReturnValue({ status: 'exited' })
await expect(
h.call('orchestration.workerStop', { dispatch: dispatchId })
).resolves.toMatchObject({ state: 'stopped', processAction: 'none' })
expect(h.runtime.closeTerminal).not.toHaveBeenCalled()
})
it('leaves an exit with no stop in flight failing the dispatch', async () => {
const { dispatchId } = await h.startWorker()
fireExit('term_worker')
@@ -127,6 +127,16 @@ export const ORCHESTRATION_WORKER_STOP_METHODS: RpcMethod[] = [
)
}
const observation = await inspectWorkerTerminal(runtime, db, params.dispatch)
// The host exit can settle this stop while terminal inspection is awaiting inventory.
if (db.getWorkerDispatch(params.dispatch)?.state === 'stopped') {
runtime.notifyMessageArrived(`dispatch:${params.dispatch}`, 'status')
return {
dispatchId: params.dispatch,
state: 'stopped',
alreadySettled: false,
processAction: 'none'
}
}
// Why `unverifiable` still proceeds: losing contact is a reason to report
// the outcome honestly, never a reason to stop trying to stop the worker.
if (