Skip to content

Commit 89821fe

Browse files
committed
fix: reset highestObservedSequence on no-progress replay to prevent unbounded retry loop
When replay makes no progress, highestObservedSequence was left at its stale high-water mark, causing resolveReplayNeedAfterRecovery to permanently return shouldReplay: true. This created an infinite 100ms polling loop with no escape. Reset highestObservedSequence to latestSequence when replay makes no progress so stale observations don't drive infinite retries. Fresh live events will re-set it via classifyDomainEvent if genuinely needed.
1 parent 5c18bad commit 89821fe

File tree

2 files changed

+6
-3
lines changed

2 files changed

+6
-3
lines changed

apps/web/src/orchestrationRecovery.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ describe("createOrchestrationRecoveryCoordinator", () => {
6565
});
6666
});
6767

68-
it("retries replay when no progress was made but higher live sequences were observed", () => {
68+
it("does not retry replay when no progress was made even if higher live sequences were previously observed", () => {
6969
const coordinator = createOrchestrationRecoveryCoordinator();
7070

7171
coordinator.beginSnapshotRecovery("bootstrap");
@@ -75,11 +75,11 @@ describe("createOrchestrationRecoveryCoordinator", () => {
7575

7676
expect(coordinator.completeReplayRecovery()).toEqual({
7777
replayMadeProgress: false,
78-
shouldReplay: true,
78+
shouldReplay: false,
7979
});
8080
expect(coordinator.getState()).toMatchObject({
8181
latestSequence: 3,
82-
highestObservedSequence: 5,
82+
highestObservedSequence: 3,
8383
pendingReplay: false,
8484
inFlight: null,
8585
});

apps/web/src/orchestrationRecovery.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ export function createOrchestrationRecoveryCoordinator() {
130130
replayStartSequence !== null && state.latestSequence > replayStartSequence;
131131
replayStartSequence = null;
132132
state.inFlight = null;
133+
if (!replayMadeProgress) {
134+
state.highestObservedSequence = state.latestSequence;
135+
}
133136
const replayResolution = resolveReplayNeedAfterRecovery();
134137
return {
135138
replayMadeProgress,

0 commit comments

Comments
 (0)