Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@


class RetryHandlerOption(RequestOption):
"""The retry request option class
"""Options for the retry handler.

Args:
delay (float): base delay in seconds that the handler adds to every computed
backoff, see ``RetryHandler.get_delay_time``. It is not a cap. Accepted range
0 to ``MAX_DELAY``. Exposed as ``max_delay``. Defaults to ``DEFAULT_DELAY``.
max_retries (int): number of retries after the first attempt, 0 to
``MAX_MAX_RETRIES``. Exposed as ``max_retry``.
should_retry (bool): whether the handler retries at all.
"""

# Default maxRetries value
Expand All @@ -14,7 +22,8 @@ class RetryHandlerOption(RequestOption):
# Default delay value in seconds
DEFAULT_DELAY: float = 3.0

# Default maximum delay value in seconds
# Largest accepted delay value in seconds. The handler also skips the retry when the
# computed delay is this value or more.
MAX_DELAY: float = 180.0

# Default value for should retry
Expand Down
48 changes: 18 additions & 30 deletions packages/http/httpx/kiota_http/middleware/retry_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,17 @@


class RetryHandler(BaseMiddleware):
"""
Middleware that allows us to specify the retry policy for all requests
Retry configuration.
:param int max_retries:
Maximum number of retries to allow. Takes precedence over other counts.
Set to ``0`` to fail on the first retry.
:param iterable retry_on_status_codes:
A set of integer HTTP status codes that we should force a retry on.
A retry is initiated if the request method is in ``allowed_methods``
and the response status code is in ``RETRY STATUS CODES``.
:param float retry_backoff_factor:
A backoff factor to apply between attempts after the second try
(most errors are resolved immediately by a second try without a
delay).
The request will sleep for::
{backoff factor} * (2 ** ({retry number} - 1))
seconds. If the backoff_factor is 0.1, then :func:`.sleep` will sleep
for [0.0s, 0.2s, 0.4s, ...] between retries. It will never be longer
than :attr:`RetryHandler.MAXIMUM_BACKOFF`.
By default, backoff is set to 0.5.
:param int retry_time_limit:
The maximum cumulative time in seconds that total retries should take.
The cumulative retry time and retry-after value for each request retry
will be evaluated against this value; if the cumulative retry time plus
the retry-after value is greater than the retry_time_limit, the failed
response will be immediately returned, else the request retry continues.
"""Retries a request on 429, 503 and 504 (``DEFAULT_RETRY_STATUS_CODES``) for the
methods in ``DEFAULT_ALLOWED_METHODS``, using the ``RetryHandlerOption`` of the
request or the one given to the constructor: ``max_retry`` (retries after the first
attempt), ``max_delay`` (a base delay, see ``get_delay_time``) and ``should_retry``.

The delay before a retry comes from ``get_delay_time``: a ``Retry-After`` response
header above zero is used as parsed, without a cap; otherwise
``backoff_factor * 2 ** (retry_count - 1)``, plus up to one second of jitter, plus
the option's ``max_delay``, capped at ``backoff_max`` (``MAXIMUM_BACKOFF``, 120
seconds, by default). No retry happens when the delay is
``RetryHandlerOption.MAX_DELAY`` (180 seconds) or more.
"""
DEFAULT_BACKOFF_FACTOR: float = 0.5

Expand Down Expand Up @@ -170,10 +155,13 @@ def check_retry_valid(self, retry_count, options):
return False

def get_delay_time(self, retry_count, response=None, delay=RetryHandlerOption.DEFAULT_DELAY):
"""
Get the time in seconds to delay between retry attempts.
Respects a retry-after header in the response if provided
If no retry-after response header, it defaults to exponential backoff
"""Get the time in seconds to delay before the next attempt.

A ``Retry-After`` response header that parses to more than zero seconds is
returned without a cap; zero or a missing header falls through to the backoff.
The backoff is ``backoff_factor * 2 ** (retry_count - 1)``, plus up to one second
of jitter, plus ``delay`` (the option's ``max_delay``, a base delay added to every
attempt), capped at ``backoff_max``.
"""
retry_after = self._get_retry_after(response)
if retry_after:
Expand Down
Loading