|
34 | 34 | exceptions.ServiceUnavailable, |
35 | 35 | requests.exceptions.ChunkedEncodingError, |
36 | 36 | requests.exceptions.ConnectionError, |
37 | | - requests.exceptions.SSLError, |
38 | 37 | requests.exceptions.Timeout, |
39 | 38 | auth_exceptions.TransportError, |
40 | 39 | ) |
41 | 40 |
|
42 | 41 | _DEFAULT_RETRY_DEADLINE = 10.0 * 60.0 # 10 minutes |
43 | 42 |
|
| 43 | +# Exceptions that are subclasses of types in _UNSTRUCTURED_RETRYABLE_TYPES |
| 44 | +# but should not be retried because they typically indicate persistent |
| 45 | +# configuration or security issues. |
| 46 | +_UNSTRUCTURED_NON_RETRYABLE_TYPES = ( |
| 47 | + requests.exceptions.SSLError, |
| 48 | +) |
| 49 | + |
44 | 50 | # Ambiguous errors (e.g. internalError, backendError, rateLimitExceeded) retry |
45 | 51 | # until the full `_DEFAULT_RETRY_DEADLINE`. This is because the |
46 | 52 | # `jobs.getQueryResults` REST API translates a job failure into an HTTP error. |
|
65 | 71 | def _should_retry(exc): |
66 | 72 | """Predicate for determining when to retry. |
67 | 73 |
|
68 | | - We retry if and only if the 'reason' is in _RETRYABLE_REASONS or is |
69 | | - in _UNSTRUCTURED_RETRYABLE_TYPES. |
| 74 | + We retry if the 'reason' is in _RETRYABLE_REASONS or if the exception |
| 75 | + is an instance of one of the _UNSTRUCTURED_RETRYABLE_TYPES, unless it |
| 76 | + is explicitly excluded by being in _UNSTRUCTURED_NON_RETRYABLE_TYPES. |
70 | 77 | """ |
| 78 | + if isinstance(exc, _UNSTRUCTURED_NON_RETRYABLE_TYPES): |
| 79 | + return False |
| 80 | + |
71 | 81 | try: |
72 | 82 | reason = exc.errors[0]["reason"] |
73 | 83 | except (AttributeError, IndexError, TypeError, KeyError): |
|
0 commit comments