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

Minimum delay #92

Open
alandtse opened this issue Feb 10, 2020 · 3 comments
Open

Minimum delay #92

alandtse opened this issue Feb 10, 2020 · 3 comments

Comments

@alandtse
Copy link

Is there a way to specify a minimum delay? For example, we want the first retry to be at 15 seconds and then increase the delay per the formula?

        a = minimum + factor * base ** n

If not, any issue if we add one? I can submit a PR.

@sryabkov
Copy link

sryabkov commented Dec 24, 2022

I was looking for how to change the initial delay, and it took a bit to figure out that factor and/or base as they are exposed, so it is possible to change them, at least for the exponential backoff. There is no example on how to do it in README.md, so I thought I'd post a short one in this thread. It is not exactly what this thread is asking for, but it gives some level of control over the initial delay.

backoff_example.py:

import backoff


def backoff_handler(details):
    print(
        "Backing off {wait:0.1f} seconds after {tries} tries "
        "calling function {target} with args {args} and kwargs "
        "{kwargs}".format(**details)
    )


@backoff.on_exception(
    backoff.expo,
    Exception,
    max_tries=5,
    on_backoff=backoff_handler,
    jitter=None,
    factor=2,
)
def myfunc():
    print("called myfunc")
    raise Exception("myfunc failed")


if __name__ == "__main__":
    myfunc()
$ python backoff_example.py
called myfunc
Backing off 2.0 seconds after 1 tries calling function <function myfunc at 0x10da554d0> with args () and kwargs {}
called myfunc
Backing off 4.0 seconds after 2 tries calling function <function myfunc at 0x10da554d0> with args () and kwargs {}
called myfunc
Backing off 8.0 seconds after 3 tries calling function <function myfunc at 0x10da554d0> with args () and kwargs {}
called myfunc
Backing off 16.0 seconds after 4 tries calling function <function myfunc at 0x10da554d0> with args () and kwargs {}
called myfunc
Traceback (most recent call last):
  File "backoff_example.py", line 26, in <module>
    myfunc()
  File "/Users/sryabkov/.asdf/installs/python/3.7.13/lib/python3.7/site-packages/backoff/_sync.py", line 105, in retry
    ret = target(*args, **kwargs)
  File "backoff_example.py", line 22, in myfunc
    raise Exception("myfunc failed")
Exception: myfunc failed

@photonbit
Copy link

For anyone coming to this issue as I did, this is the approach I took for this:

def _min_expo_wait(min_wait: float):
    """Exponential backoff with a minimum wait time."""

    def f(*args, **kwargs):
        yield max(min_wait, next(backoff.expo(*args, **kwargs), min_wait))

    return f


@backoff.on_exception(
    _min_expo_wait(60.0),
    some.Exception,
    max_tries=3,
)

The original proposed formula do not match with my expectation of exponential wait with a minimum, the code below will follow this one instead:

 a = max(minimum, factor * base ** n)

@danielbrunt57
Copy link

danielbrunt57 commented Oct 29, 2024

Here is my version for alexapy:

    def _min_expo_wait(self, min_wait: float):
        """Exponential backoff with a minimum wait time."""

        def f(*args, **kwargs):
            gen = backoff.expo(*args, **kwargs)

            while True:
                v = next(gen, None)
                _LOGGER.debug("_min_expo_wait - next(gen): %s", v)
                v =  min_wait if v is None else max(min_wait, v)
                _LOGGER.debug("_min_expo_wait - returning %s", v)
                yield v

        return f

The @backoff wrapper for async def _request():

    @backoff.on_exception(
        _min_expo_wait(random.uniform(0.2,1.2)),
        (AlexapyTooManyRequestsError, AlexapyConnectionError, ClientConnectionError),
        max_time=90,
        max_tries=10,
        jitter=None,
        # factor=2,
        logger=__name__,

and for async def _static_request():

    @staticmethod
    @backoff.on_exception(
        _min_expo_wait(random.uniform(0.8, 1.8)),
        # backoff.expo,
        (AlexapyTooManyRequestsError, AlexapyConnectionError, ClientConnectionError),
        max_time=120,
        max_tries=10,
        jitter=None,
        # factor=2,
        logger=__name__,
    )

Thank you @sryabkov and @photonbit!
and @alandtse for originally posting this over 4 years ago!!

Ref: alexapy MR !400

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

4 participants