client: add BidiStream::into_split for independently owned halves - #228
Merged
Conversation
iainmcgin
force-pushed
the
iain/bidi-into-split
branch
from
July 17, 2026 22:27
bec1838 to
8950ea0
Compare
Collaborator
Author
|
[claude code] Restacked onto the current #227 tip ( This is now targeted at the 0.9.0 release alongside #227, so it needs to land right after its parent. |
Splits a bidirectional stream into BidiSendHalf (send/close_send, Req bounds only, its own copy of the call deadline) and BidiRecvHalf (message/headers/trailers/error plus the lazy response-initialization state machine), so the two sides can be driven from separate tasks - true full duplex. The split is a plain destructure: BidiStream was already two disjoint sides internally, and no locking is added. The abort-on-drop of in-flight initialization tasks moves from BidiStream's Drop to BidiRecvHalf's Drop, which also frees BidiStream of its Drop impl so into_split can destructure; the send-before-recv field order preserves the drop sequence and is documented as load-bearing. Dropping the send half ends the request body cleanly while the RPC continues; dropping the receive half cancels the RPC, matching the behavior of dropping a whole BidiStream. BidiStream keeps its full API via thin delegation, so the change is purely additive, and generated code is unchanged. Docs state the HTTP/2 requirement for interleaved use on into_split itself, since a response-dependent send loop deadlocks on HTTP/1.1. Signed-off-by: Iain McGinniss <309153+iainmcgin@users.noreply.github.com>
iainmcgin
force-pushed
the
iain/bidi-into-split
branch
from
July 20, 2026 19:12
8950ea0 to
5c24c84
Compare
iainmcgin
marked this pull request as ready for review
July 20, 2026 19:12
iainmcgin
enabled auto-merge
July 20, 2026 19:13
azdagron
approved these changes
Jul 20, 2026
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
Adds
BidiStream::into_split, splitting a bidirectional stream into independently owned halves so the two sides can be driven from separate tasks — true full duplex:Builds on #227, now merged, and rebased onto
main; additive — no existing API changes, no codegen changes (generated bidi methods still returnBidiStream).Design
BidiStreamwas already two disjoint sides internally; the split is a plain destructure with no locking added:BidiSendHalf<Req>ownssend/close_send(and only needsReqbounds — looser than the combined impl). It carries its own copy of the whole-call deadline. Dropping it ends the request body cleanly; the RPC continues until the receive half finishes.BidiRecvHalf<B, RespView>ownsmessage/headers/trailers/errorand the lazy response-initialization state machine. The abort-on-drop of in-flight initialization tasks (client: make BidiStream receive initialization cancellation-safe #221) moves here fromBidiStream'sDrop— which also freesBidiStreamof itsDropimpl sointo_splitcan destructure. Dropping this half cancels the RPC, exactly as dropping a wholeBidiStreamdid; a code comment records that thesend-before-recvfield order is load-bearing for the drop sequence.BidiStreamkeeps its full API via thin delegation, andinto_splitsits in an unbounded impl (a pure move needs no bounds). Noreunite— documented on both halves.into_splititself (an HTTP/1.1 caller doing response-dependent sends would deadlock), and steer users toward spawned tasks over naming the halves' body type parameter.Testing
cargo semver-checksvs 0.8.1: 196/196 (additive). Net non-test size: +177 lines.