backoff icon indicating copy to clipboard operation
backoff copied to clipboard

Get status_code from invocation details

Open ericboucher opened this issue 2 years ago • 4 comments

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 avatar May 20 '22 14:05 ericboucher

@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.

bgreen-litl avatar Nov 17 '22 14:11 bgreen-litl

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?

ericboucher avatar Nov 17 '22 17:11 ericboucher

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

bgreen-litl avatar Nov 17 '22 18:11 bgreen-litl

Makes sense, thanks a lot for these details @bgreen-litl :)

ericboucher avatar Nov 22 '22 10:11 ericboucher