Skip to content

Commit eab391d

Browse files
committed
add common factor for decay
1 parent ffa29fd commit eab391d

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

README.rst

+14
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,20 @@ gets a non-falsey result could be defined like like this::
9595
def poll_for_message(queue)
9696
return queue.get()
9797

98+
99+
@backoff.factor
100+
---------------
101+
102+
The ``factor`` decorator is used to ajust other wait generator.
103+
104+
@backoff.on_predicate(backoff.factor(backoff.constant, 60), interval=1)
105+
def poll_for_message(queue)
106+
return queue.get()
107+
108+
Here `backoff.factor(backoff.constant, 60)` make backoff to sleep 60 times
109+
longer than original wait generator.
110+
111+
98112
Jitter
99113
------
100114

backoff.py

+16
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,22 @@ def constant(interval=1):
8585
yield interval
8686

8787

88+
def factor(wait_gen, f):
89+
"""Wrapped decay by factor.
90+
91+
Args:
92+
wait_gen: A generator yielding successive wait times in
93+
seconds.
94+
factor: Factor to multiply the wait_gen by.
95+
"""
96+
@functools.wraps(wait_gen)
97+
def deco(*args, **kwargs):
98+
wait = wait_gen(*args, **kwargs)
99+
while True:
100+
yield next(wait) * f
101+
return deco
102+
103+
88104
def random_jitter(value):
89105
"""Jitter the value a random number of milliseconds.
90106

backoff_tests.py

+29
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,35 @@ def succeeder(*args, **kwargs):
218218
assert details['wait'] >= 0.5 * 2 ** i
219219

220220

221+
def test_decay_factor(monkeypatch):
222+
monkeypatch.setattr('time.sleep', lambda x: None)
223+
224+
log, log_success, log_backoff, log_giveup = _log_hdlrs()
225+
226+
@backoff.on_exception(backoff.factor(backoff.expo, 0.5),
227+
Exception,
228+
on_success=log_success,
229+
on_backoff=log_backoff,
230+
on_giveup=log_giveup,
231+
jitter=backoff.random_jitter)
232+
@_save_target
233+
def succeeder(*args, **kwargs):
234+
# succeed after we've backed off twice
235+
if len(log['backoff']) < 2:
236+
raise ValueError("catch me")
237+
238+
succeeder(1, 2, 3, foo=1, bar=2)
239+
240+
# we try 3 times, backing off twice before succeeding
241+
assert len(log['success']) == 1
242+
assert len(log['backoff']) == 2
243+
assert len(log['giveup']) == 0
244+
245+
for i in range(2):
246+
details = log['backoff'][i]
247+
assert details['wait'] >= 0.5 * 2 ** i
248+
249+
221250
def test_on_exception_success_full_jitter(monkeypatch):
222251
monkeypatch.setattr('time.sleep', lambda x: None)
223252

0 commit comments

Comments
 (0)