Skip to content

Commit c29d158

Browse files
Retry(): Support negative retries value (#2110)
* Support negative `retries` value * Add unit test * Add unittest for blocking api
1 parent abd5aef commit c29d158

File tree

5 files changed

+36
-2
lines changed

5 files changed

+36
-2
lines changed

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11

2+
* Allow negative `retries` for `Retry` class to retry forever
23
* Add `items` parameter to `hset` signature
34
* Create codeql-analysis.yml (#1988). Thanks @chayim
45
* Add limited support for Lua scripting with RedisCluster

redis/asyncio/retry.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ def __init__(
2727
"""
2828
Initialize a `Retry` object with a `Backoff` object
2929
that retries a maximum of `retries` times.
30+
`retries` can be negative to retry forever.
3031
You can specify the types of supported errors which trigger
3132
a retry with the `supported_errors` parameter.
3233
"""
@@ -51,7 +52,7 @@ async def call_with_retry(
5152
except self._supported_errors as error:
5253
failures += 1
5354
await fail(error)
54-
if failures > self._retries:
55+
if self._retries >= 0 and failures > self._retries:
5556
raise error
5657
backoff = self._backoff.compute(failures)
5758
if backoff > 0:

redis/retry.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ def __init__(
1616
"""
1717
Initialize a `Retry` object with a `Backoff` object
1818
that retries a maximum of `retries` times.
19+
`retries` can be negative to retry forever.
1920
You can specify the types of supported errors which trigger
2021
a retry with the `supported_errors` parameter.
2122
"""
@@ -46,7 +47,7 @@ def call_with_retry(self, do, fail):
4647
except self._supported_errors as error:
4748
failures += 1
4849
fail(error)
49-
if failures > self._retries:
50+
if self._retries >= 0 and failures > self._retries:
5051
raise error
5152
backoff = self._backoff.compute(failures)
5253
if backoff > 0:

tests/test_asyncio/test_retry.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ async def _do(self):
5656
async def _fail(self, error):
5757
self.actual_failures += 1
5858

59+
async def _fail_inf(self, error):
60+
self.actual_failures += 1
61+
if self.actual_failures == 5:
62+
raise ConnectionError()
63+
5964
@pytest.mark.parametrize("retries", range(10))
6065
@pytest.mark.asyncio
6166
async def test_retry(self, retries: int):
@@ -68,3 +73,14 @@ async def test_retry(self, retries: int):
6873
assert self.actual_failures == 1 + retries
6974
assert backoff.reset_calls == 1
7075
assert backoff.calls == retries
76+
77+
@pytest.mark.asyncio
78+
async def test_infinite_retry(self):
79+
backoff = BackoffMock()
80+
# specify infinite retries, but give up after 5
81+
retry = Retry(backoff, -1)
82+
with pytest.raises(ConnectionError):
83+
await retry.call_with_retry(self._do, self._fail_inf)
84+
85+
assert self.actual_attempts == 5
86+
assert self.actual_failures == 5

tests/test_retry.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ def _do(self):
9595
def _fail(self, error):
9696
self.actual_failures += 1
9797

98+
def _fail_inf(self, error):
99+
self.actual_failures += 1
100+
if self.actual_failures == 5:
101+
raise ConnectionError()
102+
98103
@pytest.mark.parametrize("retries", range(10))
99104
def test_retry(self, retries):
100105
backoff = BackoffMock()
@@ -107,6 +112,16 @@ def test_retry(self, retries):
107112
assert backoff.reset_calls == 1
108113
assert backoff.calls == retries
109114

115+
def test_infinite_retry(self):
116+
backoff = BackoffMock()
117+
# specify infinite retries, but give up after 5
118+
retry = Retry(backoff, -1)
119+
with pytest.raises(ConnectionError):
120+
retry.call_with_retry(self._do, self._fail_inf)
121+
122+
assert self.actual_attempts == 5
123+
assert self.actual_failures == 5
124+
110125

111126
@pytest.mark.onlynoncluster
112127
class TestRedisClientRetry:

0 commit comments

Comments
 (0)