thriftbp: interrupt in-flight calls when their context is canceled - #720
thriftbp: interrupt in-flight calls when their context is canceled#720rokob wants to merge 1 commit into
Conversation
|
while what you described is correct, in reality, especially with framed transportation, the size in the frame envelope requires the full response to be already generated to calculate, so when you receive it on the client, that means the server already generated the full response and there's nothing really incremental there (for majority of the implementations the response are send in the same packet with the envelope). in a controlled environment this really is not something would happen. |
|
Reconnect under bursts: Release replaces the closed client synchronously via On @fishy's point: framed transport means the server buffers the full response |
|
This is intended to ensure the invariant that an RPC must stop when its absolute context deadline expires. It is exposed by what looks like a stalled mid-frame read where io.CopyN is performing multiple socket reads and blocking between them even though the entire body has been constructed on the server. I have traces taking >2s to complete when there is a fixed deadline of 1.05s. The current rolling per read socket timeout is not compatible with an absolute deadline. |
00443e0 to
b4198ef
Compare
💸 TL;DR
Make
thriftbpenforce the caller's context deadline while a pooled client is performing an RPC.After leasing a client,
clientPool.pooledCallnow closes the leased connection when the request context is canceled. Closing the connection interrupts any blocked socket read or write. The call returns the context cancellation cause, and the interrupted connection is discarded instead of being returned to the pool for reuse.Calls that complete before cancellation continue to reuse their connections normally.
📜 Details
Apache Thrift's Go header transport does not enforce the context deadline while reading a framed response body.
THeaderTransport.ReadFramechecks the context while reading the frame header, but then reads the complete body usingio.CopyN. Meanwhile,TSocket.Readsets a newnow + SocketTimeoutdeadline before every socket read. A response that continues making incremental progress can therefore run well beyond the RPC's absolute context deadline.When a client is leased:
context.Cause(ctx)when cancellation wins.The implementation also avoids racing a successful call against a late cancellation callback or closing the same client twice.
The target is enforcement of the RPC context’s absolute deadline, including stalled mid-frame reads. Although framed Thrift buffers the response before Flush, delivery over the socket remains a byte stream and the client can block after receiving only part of the frame. Closing the exclusively leased connection interrupts that read. The connection is then discarded because unread or late response bytes make protocol-safe reuse impossible.
🧪 Testing Steps / Validation
Added coverage for:
✅ Checks