From a3edb8b921e029e2c03d33302d408ad5d4e9d4ad Mon Sep 17 00:00:00 2001 From: Tim Swast Date: Tue, 23 Mar 2021 15:06:24 -0500 Subject: [PATCH] fix: add ConnectionError to default retry (#571) --- google/cloud/bigquery/retry.py | 8 ++++---- setup.py | 1 + testing/constraints-3.6.txt | 1 + tests/unit/test_retry.py | 9 +++++++++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/google/cloud/bigquery/retry.py b/google/cloud/bigquery/retry.py index 4bc4b757f..20a8e7b13 100644 --- a/google/cloud/bigquery/retry.py +++ b/google/cloud/bigquery/retry.py @@ -14,6 +14,7 @@ from google.api_core import exceptions from google.api_core import retry +import requests.exceptions _RETRYABLE_REASONS = frozenset( @@ -21,9 +22,11 @@ ) _UNSTRUCTURED_RETRYABLE_TYPES = ( + ConnectionError, exceptions.TooManyRequests, exceptions.InternalServerError, exceptions.BadGateway, + requests.exceptions.ConnectionError, ) @@ -33,10 +36,7 @@ def _should_retry(exc): We retry if and only if the 'reason' is 'backendError' or 'rateLimitExceeded'. """ - if not hasattr(exc, "errors"): - return False - - if len(exc.errors) == 0: + if not hasattr(exc, "errors") or len(exc.errors) == 0: # Check for unstructured error returns, e.g. from GFE return isinstance(exc, _UNSTRUCTURED_RETRYABLE_TYPES) diff --git a/setup.py b/setup.py index 99d3804ed..12a9bde31 100644 --- a/setup.py +++ b/setup.py @@ -35,6 +35,7 @@ "google-resumable-media >= 0.6.0, < 2.0dev", "packaging >= 14.3", "protobuf >= 3.12.0", + "requests >= 2.18.0, < 3.0.0dev", ] extras = { "bqstorage": [ diff --git a/testing/constraints-3.6.txt b/testing/constraints-3.6.txt index c4a5c51be..322373eba 100644 --- a/testing/constraints-3.6.txt +++ b/testing/constraints-3.6.txt @@ -17,5 +17,6 @@ pandas==0.23.0 proto-plus==1.10.0 protobuf==3.12.0 pyarrow==1.0.0 +requests==2.18.0 six==1.13.0 tqdm==4.7.4 diff --git a/tests/unit/test_retry.py b/tests/unit/test_retry.py index d9f867cb3..318a54d34 100644 --- a/tests/unit/test_retry.py +++ b/tests/unit/test_retry.py @@ -15,6 +15,7 @@ import unittest import mock +import requests.exceptions class Test_should_retry(unittest.TestCase): @@ -42,6 +43,14 @@ def test_w_rateLimitExceeded(self): exc = mock.Mock(errors=[{"reason": "rateLimitExceeded"}], spec=["errors"]) self.assertTrue(self._call_fut(exc)) + def test_w_unstructured_connectionerror(self): + exc = ConnectionError() + self.assertTrue(self._call_fut(exc)) + + def test_w_unstructured_requests_connectionerror(self): + exc = requests.exceptions.ConnectionError() + self.assertTrue(self._call_fut(exc)) + def test_w_unstructured_too_many_requests(self): from google.api_core.exceptions import TooManyRequests