Repository: googleapis/python-api-core

Issue:
requests.exceptions.ConnectionError retry
Hi, 

Could we add ConnectionError in list of retry so the client libraries which depend over api-core don't need to add.

`"/layers/google.python.pip/pip/lib/python3.8/site-packages/google/cloud/bigquery/client.py", line 561, in create_table api_response = self._call_api( File "/layers/google.python.pip/pip/lib/python3.8/site-packages/google/cloud/bigquery/client.py", line 574, in _call_api return call() File "/layers/google.python.pip/pip/lib/python3.8/site-packages/google/api_core/retry.py", line 281, in retry_wrapped_func return retry_target( File "/layers/google.python.pip/pip/lib/python3.8/site-packages/google/api_core/retry.py", line 184, in retry_target return target() File "/layers/google.python.pip/pip/lib/python3.8/site-packages/google/cloud/_http.py", line 472, in api_request response = self._make_request( File "/layers/google.python.pip/pip/lib/python3.8/site-packages/google/cloud/_http.py", line 336, in _make_request return self._do_request( File "/layers/google.python.pip/pip/lib/python3.8/site-packages/google/cloud/_http.py", line 374, in _do_request return self.http.request( File "/layers/google.python.pip/pip/lib/python3.8/site-packages/google/auth/transport/requests.py", line 464, in request response = super(AuthorizedSession, self).request( File "/layers/google.python.pip/pip/lib/python3.8/site-packages/requests/sessions.py", line 530, in request resp = self.send(prep, **send_kwargs) File "/layers/google.python.pip/pip/lib/python3.8/site-packages/requests/sessions.py", line 643, in send r = adapter.send(request, **kwargs) File "/layers/google.python.pip/pip/lib/python3.8/site-packages/requests/adapters.py", line 498, in send raise ConnectionError(err, request=request) requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))`

I have reached out to individually to storage,bigquery and auth sdk page to report about this issue and they have acknowledged it https://github.com/googleapis/google-auth-library-python/issues/739, https://github.com/googleapis/google-auth-library-python/issues/737, https://github.com/googleapis/python-storage/issues/414



Discussion:
parthea: @busunkim96 Here is an example of `requests.exception` in the stack trace in `python-bigquery` via https://github.com/googleapis/python-bigquery/issues/434.

Patch:
diff --git a/google/api_core/retry.py b/google/api_core/retry.py
index 43e4f07..f0f23bc 100644
--- a/google/api_core/retry.py
+++ b/google/api_core/retry.py
@@ -62,11 +62,13 @@ import logging
 import random
 import time
 
+import requests.exceptions
 import six
 
 from google.api_core import datetime_helpers
 from google.api_core import exceptions
 from google.api_core import general_helpers
+from google.auth import exceptions as auth_exceptions
 
 _LOGGER = logging.getLogger(__name__)
 _DEFAULT_INITIAL_DELAY = 1.0  # seconds
@@ -101,6 +103,8 @@ if_transient_error = if_exception_type(
     exceptions.InternalServerError,
     exceptions.TooManyRequests,
     exceptions.ServiceUnavailable,
+    requests.exceptions.ConnectionError,
+    auth_exceptions.TransportError,
 )
 """A predicate that checks if an exception is a transient API error.
 


Test patch:
diff --git a/tests/unit/test_retry.py b/tests/unit/test_retry.py
index 4c2e457..ce8f417 100644
--- a/tests/unit/test_retry.py
+++ b/tests/unit/test_retry.py
@@ -18,9 +18,11 @@ import re
 
 import mock
 import pytest
+import requests.exceptions
 
 from google.api_core import exceptions
 from google.api_core import retry
+from google.auth import exceptions as auth_exceptions
 
 
 def test_if_exception_type():
@@ -42,6 +44,8 @@ def test_if_transient_error():
     assert retry.if_transient_error(exceptions.InternalServerError(""))
     assert retry.if_transient_error(exceptions.TooManyRequests(""))
     assert retry.if_transient_error(exceptions.ServiceUnavailable(""))
+    assert retry.if_transient_error(requests.exceptions.ConnectionError(""))
+    assert retry.if_transient_error(auth_exceptions.TransportError(""))
     assert not retry.if_transient_error(exceptions.InvalidArgument(""))