Repository navigation
Conversation
Signed-off-by: bbdu3 <ergouyang854@gamil.com>
canarik
left a comment
There was a problem hiding this comment.
Thanks @bbdu3, this fixes a real hang. Holding the error in BatchState until every expected ID registers covers late registrations, and neither path resumes a continuation twice. Traced against the old code, the new public-API test times out on the error count, so it does guard the fix.
One thing before merging:
- Document the new failure behavior. When
withBatchthrows, any task fromaddRequestthat hasn't completed now fails with that error, but both doc comments still only say the error is rethrown, so a caller can't tell that awaiting those tasks no longer hangs. Could you add a line to thewithBatchandaddRequestdocs? The rest can be follow-ups.
Smaller, non-blocking:
- Duplicate request IDs can still leave a task hanging. The spec forbids reusing an ID in a session, but
request(id:)lets callers pick one, andwithBatchpasses the IDs tofinishBatchas aSet. If both registrations arrive after a failure, the second creates a fresh state with no error, so its task waits inpendingRequestsand the entry leaks. CouldaddRequestthrow on a repeated ID, with a test? Counting occurrences wouldn't help, sincependingRequestsholds one continuation per ID. - On the success path, registration still happens in a separate
Task, so a response thathandleBatchResponsesees first is dropped, and a registration afterdisconnect()is left waiting until a later disconnect. That predates this PR, so a follow-up is fine. addPendingBatchRequestandfinishBatchareinternalonly for the tests; a short comment would help, sinceaddPendingRequestnext to them isprivate.- Each registration copies
BatchStateout of the dictionary, so the set is copied every time and a large batch registers in quadratic time; mutating the entry in place avoids that.
Signed-off-by: bbdu3 <ergouyang854@gamil.com>
|
@canarik ,thanks for review, I’ve updated the I also addressed the smaller non-blocking items: rejecting duplicate IDs within a batch with regression tests, mutating I’ve left the success-path and post-disconnect registration races for a follow-up. Those require broader changes to how registration coordinates with sending, response handling, and disconnect, plus dedicated concurrency tests. Keeping them separate preserves the scope of this failure-cleanup fix. Duplicate-ID validation is also limited to the current batch; it does not track IDs across the entire session. The build and all 502 Linux tests passed with Swift 6.1, and DocC passed with |
Summary
When
Client.withBatchthrows, tasks returned byBatch.addRequestcan remain suspended. Registration happens asynchronously, so cleaning up only the requests already registered at failure time misses continuations that register later.This change coordinates batch completion and request registration on the
Clientactor. It handles both transport send failures and a body closure that throws after adding requests.Fixes #324.
Changes
Tests
Validated the final implementation in an isolated WSL Ubuntu 22.04 environment with Swift 6.1:
swift buildpassed.ClientTestspassed.git diff --checkpassed.Regression coverage includes send failure, body closure failure, registration before and after failure, multiple late registrations, batch isolation, an already-completed response, and continued connection usability.
As a negative control, the public-API regression test was run against the original implementation. Both send failure and body closure failure reproduced the issue: neither child task completed before disconnect. Both cases pass with the fix.