Skip to content

Commit 57a95cf

Browse files
authored
Exponential with jitter backoff (#3550)
1 parent 7a36e8b commit 57a95cf

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

redis/backoff.py

+15
Original file line numberDiff line numberDiff line change
@@ -110,5 +110,20 @@ def compute(self, failures: int) -> float:
110110
return self._previous_backoff
111111

112112

113+
class ExponentialWithJitterBackoff(AbstractBackoff):
114+
"""Exponential backoff upon failure, with jitter"""
115+
116+
def __init__(self, cap: float = DEFAULT_CAP, base: float = DEFAULT_BASE) -> None:
117+
"""
118+
`cap`: maximum backoff time in seconds
119+
`base`: base backoff time in seconds
120+
"""
121+
self._cap = cap
122+
self._base = base
123+
124+
def compute(self, failures: int) -> float:
125+
return min(self._cap, random.random() * self._base * 2**failures)
126+
127+
113128
def default_backoff():
114129
return EqualJitterBackoff()

tests/test_backoff.py

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from unittest.mock import Mock
2+
3+
import pytest
4+
5+
from redis.backoff import ExponentialWithJitterBackoff
6+
7+
8+
def test_exponential_with_jitter_backoff(monkeypatch: pytest.MonkeyPatch) -> None:
9+
mock_random = Mock(side_effect=[0.25, 0.5, 0.75, 1.0, 0.9])
10+
monkeypatch.setattr("random.random", mock_random)
11+
12+
bo = ExponentialWithJitterBackoff(cap=5, base=1)
13+
14+
assert bo.compute(0) == 0.25 # min(5, 0.25*2^0)
15+
assert bo.compute(1) == 1.0 # min(5, 0.5*2^1)
16+
assert bo.compute(2) == 3.0 # min(5, 0.75*2^2)
17+
assert bo.compute(3) == 5.0 # min(5, 1*2^3)
18+
assert bo.compute(4) == 5.0 # min(5, 0.9*2^4)

0 commit comments

Comments
 (0)