backoff
backoff copied to clipboard
Get status_code from invocation details
When writing a backoff_handler
, it would be very useful for us to have access to some information about the failed response.
Currently, the availables details are as follows.
class _Details(TypedDict):
target: Callable[..., Any]
args: Tuple[Any, ...]
kwargs: Dict[str, Any]
tries: int
elapsed: float
class Details(_Details, **details_kwargs):
wait: float # present in the on_backoff handler case for either decorator
value: Any # present in the on_predicate decorator case
Would it be possible to add the Response.status_code? Or even maybe the full Response?
PS - Thanks for this awesome tool!
@ericboucher I need more information here. What backoff decorator are you using? What is the function you are decorating? A minimal code example would help.
Hi @bgreen-litl, this is our code at the moment to bypass this. And here is a link to the code https://github.com/MeltanoLabs/tap-github/blob/main/tap_github/client.py#L264
def backoff_handler(self, details: Details) -> None:
"""Handle retriable error by swapping auth token."""
self.logger.info("Retrying request with different token")
# use python introspection to obtain the error object
# FIXME: replace this once https://github.com/litl/backoff/issues/158
# is fixed
exc = cast(
FrameType,
cast(FrameType, cast(FrameType, inspect.currentframe()).f_back).f_back,
).f_locals["e"]
if exc.response.status_code == 403 and "rate limit exceeded" in str(
exc.response.content
):
# we hit a rate limit, rotate token
prepared_request = details["args"][0]
self.authenticator.get_next_auth_token()
prepared_request.headers.update(self.authenticator.auth_headers or {})
Ideally, we could get the response.status_code directly in details
without the need for the hack above. What do you think?
You're only showing me the handler, not the declaration of backoff decorator, but it looks like you must be using the on_exception
decorator, so I will make a few guesses.
You've always been able to get the Exception instance in the backoff handlers, see the "Getting exception info" section in the README. The short version is use sys.exc_info()
- you shouldn't need any of that introspection stuff. In addition, there is now an "exception"
key in the details dict since 2.2 which will have the exception instance.
backoff is not tightly coupled to requests
(presumably what you're using above) or any other library so status_code
or any other application specific data is not something that would be in details dict.
You also might want to look at the backoff.runtime
wait generator which was introduced in large part to address rate limiting concerns. https://github.com/litl/backoff#backoffruntime
Makes sense, thanks a lot for these details @bgreen-litl :)