Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get status_code from invocation details #158

Open
ericboucher opened this issue May 20, 2022 · 4 comments
Open

Get status_code from invocation details #158

ericboucher opened this issue May 20, 2022 · 4 comments

Comments

@ericboucher
Copy link

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!

@bgreen-litl
Copy link
Member

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

@ericboucher
Copy link
Author

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?

@bgreen-litl
Copy link
Member

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

@ericboucher
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants