Fix gRPC client interceptor breaking bidirectional streaming (#1180)#4259
Open
juandelacruz-calvo wants to merge 1 commit intoopen-telemetry:mainfrom
Open
Fix gRPC client interceptor breaking bidirectional streaming (#1180)#4259juandelacruz-calvo wants to merge 1 commit intoopen-telemetry:mainfrom
juandelacruz-calvo wants to merge 1 commit intoopen-telemetry:mainfrom
Conversation
…lemetry#1180) Route bidi (stream-stream) RPCs through `_intercept` instead of the generator-based `_intercept_server_stream`. The generator wrapper strips the grpc.Call/grpc.Future interface, causing downstream code (e.g. google.api_core.bidi.BidiRpc) to crash with: AttributeError: 'generator' object has no attribute 'add_done_callback' The fix adds `and not client_info.is_client_stream` to the condition in `intercept_stream()` so only unary-stream RPCs use the generator path. Includes a regression test verifying the bidi stream response preserves the grpc.Call interface (add_done_callback, cancel, is_active). Co-authored-by: Cursor <cursoragent@cursor.com>
Author
|
I have created an even simpler PR to fix the issues with PubSub that hopefully should be simpler to get approval for 🙏 |
Author
|
For anyone needing a fix, this monkey patch should do: |
Contributor
|
Thanks for contributing! Please could you make sure the existing tests all still pass or are adjusted. For example when |
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
AttributeError: 'generator' object has no attribute 'add_done_callback'by routing bidi streams through_interceptinstead of the generator-based_intercept_server_stream(issue Thread-ConsumeBidirectionalStream caught unexpected exception 'generator' object has no attribute 'add_done_callback' and will exit. #1180)test_stream_stream_preserves_call_interfaceverifying the bidi stream response preserves thegrpc.Callinterface (add_done_callback,cancel,is_active)Root Cause
In
_client.py,intercept_stream()routed all RPCs withis_server_stream=Trueinto_intercept_server_stream(), including bidirectional streams (where bothis_client_streamandis_server_streamareTrue)._intercept_server_streamis a generator function (usesyield from), so calling it returns a bare Python generator that lacks thegrpc.Callinterface (add_done_callback,cancel,is_active, etc.).Downstream code — notably
google.api_core.bidi.BidiRpc.open()used by Google Cloud Pub/Sub — expects a real gRPC call object and crashes:The Fix
One condition change in
intercept_stream():This ensures only unary-stream RPCs use the generator-based
_intercept_server_stream. Bidi streams fall through to_intercept, which preserves thegrpc.Call/grpc.Futureinterface._intercept_server_stream_intercept_server_stream(unchanged)_intercept_intercept(unchanged)_intercept_server_stream(broken)_intercept(fixed)Files Changed
instrumentation/.../grpc/_client.pyinstrumentation/.../tests/test_client_interceptor.pytest_stream_stream_preserves_call_interfaceCHANGELOG.mdTest plan
test_stream_streamcontinues to pass (span correctness)test_stream_stream_preserves_call_interfacepasses — verifiesgrpc.Callattributes on bidi responseMade with Cursor