Source code for wheezy.core.retry
""" ``retry`` module.
"""
from time import time
from time import sleep
def make_retry(timeout, start, end=None, slope=1.0, step=0.0):
[docs] """ Return a function that accepts a single argument ``acquire`` which
should be a callable (without any arguments) that returns a boolean
value when attempt to acquire some resource or perform operation
succeeded or not.
If a first attempt fails the retry function sleeps for ``start``
and later delay time is increased linearly per ``slope`` and
``step`` until ``end``. A last delay is a time remaining.
A total retry time is limited by ``timeout``.
``timeout`` - a number of seconds for the entire retry operation
from the first failed attempt to the last (excluding time for both
acquire operations).
``start`` - a time for initial delay.
``end`` - a time for a longest delay between retry attempts.
``slope`` and ``step`` - coefficients for linear calculation of
the next delay.
Example 1::
# delays: 0.5, 0.5, 0.5, 0.5
retry = make_retry(timeout=10.0, start=0.5)
Example 2::
# delays: 0.5, 0.1, 1.5, 2.0
retry = make_retry(timeout=10.0, start=0.5, end=2.0, step=0.5)
Example 3::
# delays: 0.05, 0.1, 0.2, 0.4, 0.8, 1.6, 2.0
retry = make_retry(timeout=10.0, start=0.05, end=2.0, slope=2.0)
if retry(lambda: acquire('something')):
# good to go
else:
# timed out
"""
end = end is None and start or end
assert timeout > 0.0
assert start >= 0.0
assert end >= 0.0
assert timeout > end
assert slope >= 1.0
assert step >= 0.0
assert start <= end
def retry(acquire):
if acquire():
return True
expires = time() + timeout
delay = start
sleep(delay)
while True:
if acquire():
return True
remains = expires - time()
if remains < delay:
break
if delay < end:
delay = delay * slope + step
if delay > end:
delay = end
sleep(delay)
if remains <= 0.0:
return False
sleep(remains)
return acquire()
return retry