Skip to content

Commit 20bb5f7

Browse files
authored
Fix Response Error Caching in Streaming Interceptors (#248)
1 parent 5e04e04 commit 20bb5f7

File tree

2 files changed

+27
-8
lines changed

2 files changed

+27
-8
lines changed

google/ads/google_ads/interceptors/interceptor.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,6 @@ def __init__(self, api_version):
155155
self._error_protos = None
156156
self._failure_key = (
157157
f'google.ads.googleads.{api_version}.errors.googleadsfailure-bin')
158-
self._exception = None
159158
self._api_version = api_version
160159

161160
def _get_error_from_response(self, response):
@@ -182,9 +181,6 @@ def _get_error_from_response(self, response):
182181
Exception: If not a GoogleAdsException or RpcException the error
183182
will be raised as-is.
184183
"""
185-
if self._exception:
186-
return self._exception
187-
188184
status_code = response.code()
189185
response_exception = response.exception()
190186

@@ -200,20 +196,19 @@ def _get_error_from_response(self, response):
200196
# library-specific Error type for easy handling. These errors
201197
# originate from the Google Ads API and are often caused by
202198
# invalid requests.
203-
self._exception = GoogleAdsException(
199+
return GoogleAdsException(
204200
response_exception, response, google_ads_failure,
205201
request_id)
206202
else:
207203
# Raise the original exception if not a GoogleAdsFailure. This
208204
# type of error is generally caused by problems at the request
209205
# level, such as when an invalid endpoint is given.
210-
self._exception = response_exception
206+
return response_exception
211207
else:
212208
# Raise the original exception if error has status code
213209
# INTERNAL or RESOURCE_EXHAUSTED, meaning that
214-
self._exception = response_exception
210+
return response_exception
215211

216-
return self._exception
217212

218213
def _get_google_ads_failure(self, trailing_metadata):
219214
"""Gets the Google Ads failure details if they exist.

tests/interceptors/interceptor_test.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import mock
1919
from unittest import TestCase
2020

21+
import grpc
22+
2123
from google.ads.google_ads.client import _DEFAULT_VERSION as default_version
2224
from google.ads.google_ads.interceptors.interceptor import Interceptor
2325

@@ -105,3 +107,25 @@ def test_deferred_error_proto_module_load(self):
105107
import_mock.assert_called_once_with('google.ads.google_ads.'
106108
f'{default_version}.proto.'
107109
'errors.errors_pb2')
110+
111+
def test_get_error_from_response_does_not_cache_error(self):
112+
"""Ensures errors are not cached across requests.."""
113+
interceptor = Interceptor(default_version)
114+
115+
class MockRpcErrorResponse(grpc.RpcError):
116+
def code(self):
117+
return grpc.StatusCode.INVALID_ARGUMENT
118+
119+
def trailing_metadata(self):
120+
return ((
121+
interceptor._failure_key,
122+
b"\n \n\x02\x08\x10\x12\x1aInvalid customer ID '123'."),)
123+
124+
def exception(self):
125+
return self
126+
127+
response = MockRpcErrorResponse()
128+
129+
first_result = interceptor._get_error_from_response(response)
130+
second_result = interceptor._get_error_from_response(response)
131+
self.assertIsNot(first_result, second_result)

0 commit comments

Comments
 (0)