[world-vercel] Propagate cancel from getReadable() to upstream fetch#1801
Draft
VaguelySerious wants to merge 4 commits intostablefrom
Draft
[world-vercel] Propagate cancel from getReadable() to upstream fetch#1801VaguelySerious wants to merge 4 commits intostablefrom
VaguelySerious wants to merge 4 commits intostablefrom
Conversation
🦋 Changeset detectedLatest commit: 4a98ba5 The changes in this PR will be included in the next version bump. This PR includes changesets to release 18 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 |
Contributor
Contributor
🧪 E2E Test Results❌ Some tests failed Summary
❌ Failed Tests▲ Vercel Production (1 failed)astro (1 failed):
Details by Category❌ ▲ Vercel Production
✅ 🪟 Windows
❌ Some E2E test jobs failed:
Check the workflow run for details. |
When a consumer cancels the ReadableStream returned by `readFromStream` (e.g. an HTTP client hanging up on an endpoint that pipes `run.getReadable()`), the pull loop could continue running and even trigger a fresh reconnect via `connect()` — the new fetch was never tied to the cancellation, so the request kept running in the background. Fix: - Track a `cancelled` flag that `pull` checks before and after each read and before each reconnect. - Plumb an `AbortController.signal` into `fetch` so the in-flight upstream request (including a pending reconnect) is aborted when the consumer cancels. Regression tests cover the abort-signal contract, the mid-timeout reconnect race, and cancel-during-read. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Peter Wielander <mittgfu@gmail.com>
6e2acd6 to
85cb3dc
Compare
Signed-off-by: Peter Wielander <mittgfu@gmail.com>
VaguelySerious
added a commit
that referenced
this pull request
Apr 17, 2026
When a consumer cancels the ReadableStream returned by streams.get (e.g. an HTTP client hanging up on an endpoint that pipes `run.getReadable()`), the pull loop could continue running and even trigger a fresh reconnect via `connect()` — the new fetch was never tied to the cancellation, so the request kept running in the background. Fix: - Track a `cancelled` flag that `pull` checks before and after each read and before each reconnect. - Plumb an `AbortController.signal` into `fetch` so the in-flight upstream request (including a pending reconnect) is aborted when the consumer cancels. Regression tests cover the abort-signal contract, the mid-timeout reconnect race, and cancel-during-read. Port of #1801 (targeting `stable`). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Peter Wielander <mittgfu@gmail.com>
3 tasks
VaguelySerious
added a commit
to vercel/workflow-examples
that referenced
this pull request
Apr 17, 2026
- Point workflow tarballs at peter/fix-stream-cancel-reconnect branch preview - Log request.signal.aborted in the stream route The companion workflow PR (vercel/workflow#1801) adds cancel propagation to world-vercel readFromStream. World-vercel's cancel handler logs 'Cancelling stream' when hit; combined with the route.ts log, we can trace whether the cancel makes it all the way through. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Peter Wielander <mittgfu@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a regression from #1790 / #1742: when a consumer cancels the
ReadableStreamreturned byrun.getReadable()(e.g. an HTTP client disconnects from an API route that pipes the stream out), the pull loop inreadFromStreamkept running and could trigger further reconnects in the background. The in-flight upstream fetch was never aborted, so the endpoint kept fetching long after the client had gone away.Root cause
Two things combined:
cancelledflag —pullhad no way to know the consumer asked to stop.AbortSignalon the upstreamfetch()— even if we noticed, there was no way to unblock a pending request.The
cancelhandler only calledreader.cancel()on whichever reader was captured at that moment. Ifpullwas mid-reconnect (reader = await connect()),cancelcancelled the stale reader; the new fetch then connected and kept streaming.Fix
cancelledflag thatpullchecks before and after eachreader.read()and before eachconnect().AbortController.signalintofetch, aborted fromcancel, so the in-flight request (including a pending reconnect) unblocks.connect()failures triggered by abort are swallowed silently whencancelled.Tests
Three new tests under `readFromStream reconnection > consumer cancel`:
All 70 world-vercel tests pass.
Note
The same bug exists on `main` (the original #1742 implementation that `main` carries). Will open a separate PR for that once this lands.
Test plan
🤖 Generated with Claude Code