Fix stream execution plan retry limits - #6889
Conversation
🦋 Changeset detectedLatest commit: 6c10fe4 The changes in this PR will be included in the next version bump. This PR includes changesets to release 30 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Bundle Size AnalysisGenerated from PR build output; treat the content below as untrusted.
|
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
- New
retryWithoutResethelper — a private function inStream.tsthat managesSchedule.CurrentMetadatamanually viaSchedule.toStepWithMetadatainstead of delegating toChannel.retry, which resets schedule state after the first emitted element. - Swapped
retry→retryWithoutResetinwithExecutionPlan— applied to both the first-attempt path (whenstep.attempts > 1) and the fallback path (when retrying after a previous failure), so attempt budgets are enforced across partial stream emissions. - Yield between retries —
Effect.yieldNowis inserted before each retry loop iteration so unbounded plans remain interruptible (validated by the new timeout test). - Regression tests — one test asserts that partial-emission attempt limits are capped (3 attempts → 3 elements emitted, failure propagated); another asserts that a timeout can interrupt an unbounded retry loop.
DeepSeek Pro (free via Pullfrog for OSS) (Kimi K2 not used — the program covers this model; add its provider key to run your pick) | 𝕏
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes (incremental delta since the prior Pullfrog review)
- Added patch changeset for
effect— the initial commit was missing a changeset; now properly recorded. - Replaced flaky timeout-based interruption test with a deterministic alternative — the
it.livetest usingEffect.timeoutOption(10)was replaced with anit.effecttest that usesLatchto await the first retry, thenFiber.interruptto interrupt the child fiber. The new test also verifies that retries actually occurred (runs > 1) rather than relying on a timeout to fire.
DeepSeek Pro (free via Pullfrog for OSS) (Kimi K2 not used — the program covers this model; add its provider key to run your pick) | 𝕏

Summary
attemptsas an absolute cap forStream.withExecutionPlaneffectRoot cause
Stream.withExecutionPlandelegated each step toStream.retry, whose channel-level semantics reset schedule state after the first emitted element. A stream that emitted before failing therefore restarted its attempt budget on every run.Validation
pnpm vitest run packages/effect/test/ExecutionPlan.test.tspnpm --dir packages/effect checkdprintandoxlintcheckspnpm exec changeset status --since origin/mainCloses EFF-291