diff --git a/google/api_core/retry.py b/google/api_core/retry.py index 6198bfd1..98b8bbd9 100644 --- a/google/api_core/retry.py +++ b/google/api_core/retry.py @@ -93,19 +93,23 @@ class RetryFailureReason(Enum): """ The cause of a failed retry, used when building exceptions """ + TIMEOUT = "TIMEOUT" NON_RETRYABLE_ERROR = "NON_RETRYABLE_ERROR" def _build_retry_error( - exc_list: list[Exception], reason: RetryFailureReason, timeout_val: float, **kwargs: Any + exc_list: list[Exception], + reason: RetryFailureReason, + timeout_val: float, + **kwargs: Any, ) -> tuple[Exception, Exception | None]: """ Default exception_factory implementation. Builds an exception after the retry fails Args: - exc_list (list[Exception]): list of exceptions that occurred during the retry - - reason (google.api_core.retry.RetryFailureReason): reason for the retry failure. + - reason (google.api_core.retry.RetryFailureReason): reason for the retry failure. Can be TIMEOUT or NON_RETRYABLE_ERROR - timeout_val (float): the original timeout value for the retry, for use in the exception message diff --git a/google/api_core/retry_streaming.py b/google/api_core/retry_streaming.py index bd93d235..114b47fd 100644 --- a/google/api_core/retry_streaming.py +++ b/google/api_core/retry_streaming.py @@ -94,7 +94,9 @@ def retry_target_stream( timeout = kwargs.get("deadline", timeout) deadline: Optional[float] = time.monotonic() + timeout if timeout else None error_list: List[Exception] = [] - exc_factory = partial(exception_factory or retries._build_retry_error, timeout_val=timeout) + exc_factory = partial( + exception_factory or retries._build_retry_error, timeout_val=timeout + ) for sleep in sleep_generator: # Start a new retry loop @@ -109,14 +111,17 @@ def retry_target_stream( error_list.append(exc) if not predicate(exc): final_exc, source_exc = exc_factory( - exc_list=error_list, reason=retries.RetryFailureReason.NON_RETRYABLE_ERROR + exc_list=error_list, + reason=retries.RetryFailureReason.NON_RETRYABLE_ERROR, ) raise final_exc from source_exc if on_error is not None: on_error(exc) if deadline is not None and time.monotonic() + sleep > deadline: - final_exc, source_exc = exc_factory(exc_list=error_list, reason=retries.RetryFailureReason.TIMEOUT) + final_exc, source_exc = exc_factory( + exc_list=error_list, reason=retries.RetryFailureReason.TIMEOUT + ) raise final_exc from source_exc _LOGGER.debug( "Retrying due to {}, sleeping {:.1f}s ...".format(error_list[-1], sleep) diff --git a/google/api_core/retry_streaming_async.py b/google/api_core/retry_streaming_async.py index 96c03aec..cd733e1c 100644 --- a/google/api_core/retry_streaming_async.py +++ b/google/api_core/retry_streaming_async.py @@ -165,7 +165,9 @@ async def retry_target_stream( except (Exception, asyncio.CancelledError) as exc: error_list.append(exc) if not predicate(exc): - exc, source_exc = exc_factory(exc_list=error_list, reason=RetryFailureReason.NON_RETRYABLE_ERROR) + exc, source_exc = exc_factory( + exc_list=error_list, reason=RetryFailureReason.NON_RETRYABLE_ERROR + ) raise exc from source_exc if on_error is not None: on_error(exc) @@ -175,7 +177,9 @@ async def retry_target_stream( # sleep and adjust timeout budget if deadline is not None and time.monotonic() + sleep > deadline: - final_exc, source_exc = exc_factory(exc_list=error_list, reason=RetryFailureReason.TIMEOUT) + final_exc, source_exc = exc_factory( + exc_list=error_list, reason=RetryFailureReason.TIMEOUT + ) raise final_exc from source_exc _LOGGER.debug( "Retrying due to {}, sleeping {:.1f}s ...".format(error_list[-1], sleep)