Repository navigation
fix(peer): release the request body when the signal is already aborted - #127
Conversation
ClientPeer.request() checked the signal before transmitRequest ran, so an already-aborted signal rejected the request without cancelling a ReadableStream body or returning an async iterator body. The check now runs at the start of transmitRequest, so this case goes through the same cleanup as every other exit before the body is sent.
@standard-server/aws-lambda
@standard-server/core
@standard-server/fastify
@standard-server/fetch
@standard-server/node
@standard-server/peer
@standard-server/shared
commit: |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Merging this PR will not alter performance
Comparing Footnotes
|
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
packages/peer/src/client.ts— move the abort check into the transmit path.request()no longer callsthrowIfAborted(signal)synchronously; the check moves to the first statement oftransmitRequest'stry(beforeencodeAtomicStandardBody). A pre-aborted signal now flows through the existingcatch→closeByIdrejection and the pre-existingfinally→cancelStandardBody, releasing aReadableStreambody or returning an async-iterator body. This reuses the same cleanup path already exercised by abort-during-encode/send, peer close, and send failure.packages/peer/src/client.test.ts— two regression cases. One per body type undersignal / abort, asserting the body is released with the abort reason, nothing is sent, and no request state remains.
I traced the cleanup and race behavior: for a pre-aborted signal the abort listener never fires (addEventListener on an already-aborted signal is a no-op), closeById removes it and the state, and only transmitRequest's finally cancels the body, so there is no double cleanup. The check still sits before body encoding, so the stated "no change to the success path" holds.
I also confirmed the tests are discriminating: with base packages/peer/src/client.ts (28db1dd) restored, both new cases fail with expected "vi.fn()" to be called once, but got 0 times. Full peer client suite (55 tests), tsc -b, and eslint on both files are clean.
DeepSeek Flash (default — pick a model for stronger reviews) | 𝕏

When
ClientPeer.request()was called with a signal that was already aborted, the request rejected but its body was never cleaned up. AReadableStreambody was never cancelled, and an async iterator body never ran itsreturn(), so any resources behind it stayed open. That body is now released with the abort reason, the same way as when the request ends before sending for any other reason.Fixes
ReadableStreamrequest body with the abort reason, and returns an async iterator body.Performance
Testing
main.vitest run packages/peer(254 passed),eslint, andtsc -bare clean.