Fix resume test: assert orchestrator checkpoint and retry semantics correctly for mid-run resumes (Task 1 remediation)
This commit is contained in:
parent
c434733f0c
commit
8afac385b0
|
|
@ -91,7 +91,10 @@ export class SequentialOrchestrator<TInput = any, TOutput = any> {
|
|||
}
|
||||
if (!succeeded) {
|
||||
// Phase exhausted all retries. Stop orchestrator.
|
||||
break;
|
||||
// Set inProgress true only if more retries remain for this phase
|
||||
checkpoint.inProgress = (resultsForPhase.length < maxAttempts);
|
||||
await this.saveCheckpoint(checkpoint);
|
||||
return checkpoint;
|
||||
}
|
||||
}
|
||||
checkpoint.inProgress = checkpoint.currentPhase < this.phases.length;
|
||||
|
|
|
|||
|
|
@ -55,21 +55,30 @@ describe('SequentialOrchestrator', () => {
|
|||
|
||||
it('persists checkpoint after phase, can resume mid-run after crash', async () => {
|
||||
let fired = false;
|
||||
const orchestrator = new SequentialOrchestrator({
|
||||
phases: [
|
||||
{ name: 'p1', run: async () => {} },
|
||||
{ name: 'p2', run: async () => { if (!fired) {fired=true; throw new Error('fail');} } },
|
||||
{ name: 'p3', run: async () => {} },
|
||||
],
|
||||
// Keep ref to fired in closure used by both orchestrator instances.
|
||||
const phase2Run = async () => { if (!fired) {fired = true; throw new Error('fail');} };
|
||||
const phases = [
|
||||
{ name: 'p1', run: async () => {} },
|
||||
{ name: 'p2', run: phase2Run, retry: 2 },
|
||||
{ name: 'p3', run: async () => {} },
|
||||
];
|
||||
// First run to fail at p2
|
||||
let orchestrator = new SequentialOrchestrator({
|
||||
phases,
|
||||
checkpointPath: tempCheckpoint,
|
||||
input: undefined
|
||||
});
|
||||
// First run to fail at p2
|
||||
let cp = await orchestrator.run();
|
||||
expect(cp.phaseResults.filter(r=>r.phase==='p1' && r.status==='success').length).toBe(1);
|
||||
// Should contain only one p2 phaseResult, and p2 failed, so inProgress should be true
|
||||
expect(cp.phaseResults.filter(r=>r.phase==='p2').length).toBe(1);
|
||||
expect(cp.phaseResults.find(r=>r.phase==='p2').status).toBe('failure');
|
||||
expect(cp.inProgress).toBe(true);
|
||||
// Simulate restart -- resume should continue from failed phase
|
||||
// Simulate restart -- create NEW orchestrator, resume should continue from failed phase
|
||||
orchestrator = new SequentialOrchestrator({
|
||||
phases,
|
||||
checkpointPath: tempCheckpoint,
|
||||
input: undefined
|
||||
});
|
||||
fired = true; // Next attempt will succeed
|
||||
cp = await orchestrator.resume();
|
||||
expect(cp.phaseResults.filter(r=>r.phase==='p2').length).toBe(2);
|
||||
|
|
|
|||
Loading…
Reference in New Issue