Repository navigation
Fix: request hang on a failing Future payload - #193
Merged
Merged
Conversation
An `APIResponse` with a `Future` payload that fails never got a response: the `Future` is created inside the `APIRoot.call` error `Zone`, and errors don't cross error zones, so `APIServer.resolveBody` (listening outside it) never received the error (only logged as an uncaught asynchronous error). - `APIRoot` records the call `Zone` of a `Future` payload (`APIResponse.payloadZone`), and `resolveBody` listens to it there (`APIResponse.runInPayloadZone`). Its result, an error `APIResponse` on failure, is a value: delivered to any zone. The request gets a `500`. - Tests: HTTP (`500`, also compressed) and `resolveBody` with the `payloadZone`. Both time out without the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #193 +/- ##
==========================================
+ Coverage 95.61% 95.66% +0.04%
==========================================
Files 75 75
Lines 25747 25754 +7
==========================================
+ Hits 24619 24637 +18
+ Misses 1128 1117 -11
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
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.
Stacked on #192 (base
feat/brotli). Merge #192 first; this PR's diff is only the fix.Bug
A route whose
APIResponsehas aFuturepayload that fails never gets a response: the request hangs until the client gives up. It already happens onmaster, so this PR doesn't depend on Brotli.The server only logs
Uncaught asynchronous error while calling: APIRequest#...and never answers.Cause
APIRootruns each call in its own errorZone(handleUncaughtError). The route creates the payloadFutureinside that zone, andAPIServer.resolveBodylistens to it (then(..., onError: ...)) from outside. Dart never delivers aFutureerror to a listener in a different error zone. It's reported as uncaught in the zone where theFuturewas created instead. So theonErrorthat builds the500response never runs, and the future it returns never completes.Fix
APIRootrecords the call zone of aFuturepayload:APIResponse.payloadZone.resolveBodylistens to the payload inside that zone (APIResponse.runInPayloadZone), so it receives the error. Its result is a value (an errorAPIResponseon failure), and values cross zones normally. The request gets a500, compressed like any other response.Futurehas nopayloadZone, and nothing changes for it.Tests
Futurepayload returns500, uncompressed withoutAccept-Encoding, and compressed withbrandgzip.APIRoot.calland thenresolveBody:payloadZoneis set, the errorAPIResponseis received, a successfulFuturepayload still resolves, and a payload that isn't aFuturehas no zone.dart format,dart analyze --fatal-infosand the full suite, including the Docker DB suites, all pass, and so doesensure_build.🤖 Generated with Claude Code