fix: ensure exception is available when BackgroundConsumer open stream fails (#357)
* fix: ensure exception is available when BackgroundConsumer open stream fails
* chore: fix coverage
* Address review comments
* revert
* address review feedback
* raise grpc.RpcError instead of GoogleAPICallError
* 🦉 Updates from OwlBot post-processor
See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md
---------
Co-authored-by: Rosie Zou <rosiezou@users.noreply.github.com>
Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
diff --git a/google/api_core/bidi.py b/google/api_core/bidi.py
index 57f5f9d..74abc49 100644
--- a/google/api_core/bidi.py
+++ b/google/api_core/bidi.py
@@ -92,10 +92,7 @@
# Note: there is a possibility that this starts *before* the call
# property is set. So we have to check if self.call is set before
# seeing if it's active.
- if self.call is not None and not self.call.is_active():
- return False
- else:
- return True
+ return self.call is not None and self.call.is_active()
def __iter__(self):
if self._initial_request is not None:
@@ -265,6 +262,10 @@
self._callbacks.append(callback)
def _on_call_done(self, future):
+ # This occurs when the RPC errors or is successfully terminated.
+ # Note that grpc's "future" here can also be a grpc.RpcError.
+ # See note in https://github.com/grpc/grpc/issues/10885#issuecomment-302651331
+ # that `grpc.RpcError` is also `grpc.call`.
for callback in self._callbacks:
callback(future)
@@ -276,7 +277,13 @@
request_generator = _RequestQueueGenerator(
self._request_queue, initial_request=self._initial_request
)
- call = self._start_rpc(iter(request_generator), metadata=self._rpc_metadata)
+ try:
+ call = self._start_rpc(iter(request_generator), metadata=self._rpc_metadata)
+ except exceptions.GoogleAPICallError as exc:
+ # The original `grpc.RpcError` (which is usually also a `grpc.Call`) is
+ # available from the ``response`` property on the mapped exception.
+ self._on_call_done(exc.response)
+ raise
request_generator.call = call
diff --git a/tests/unit/test_bidi.py b/tests/unit/test_bidi.py
index f5e2b72..84ac9dc 100644
--- a/tests/unit/test_bidi.py
+++ b/tests/unit/test_bidi.py
@@ -804,6 +804,21 @@
while consumer.is_active:
pass
+ def test_rpc_callback_fires_when_consumer_start_fails(self):
+ expected_exception = exceptions.InvalidArgument(
+ "test", response=grpc.StatusCode.INVALID_ARGUMENT
+ )
+ callback = mock.Mock(spec=["__call__"])
+
+ rpc, _ = make_rpc()
+ bidi_rpc = bidi.BidiRpc(rpc)
+ bidi_rpc.add_done_callback(callback)
+ bidi_rpc._start_rpc.side_effect = expected_exception
+
+ consumer = bidi.BackgroundConsumer(bidi_rpc, on_response=None)
+ consumer.start()
+ assert callback.call_args.args[0] == grpc.StatusCode.INVALID_ARGUMENT
+
def test_consumer_expected_error(self, caplog):
caplog.set_level(logging.DEBUG)