Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

* Allow negative `retries` for `Retry` class to retry forever
* Add `items` parameter to `hset` signature
* Create codeql-analysis.yml (#1988). Thanks @chayim
* Add limited support for Lua scripting with RedisCluster
Expand Down
3 changes: 2 additions & 1 deletion redis/asyncio/retry.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def __init__(
"""
Initialize a `Retry` object with a `Backoff` object
that retries a maximum of `retries` times.
`retries` can be negative to retry forever.
You can specify the types of supported errors which trigger
a retry with the `supported_errors` parameter.
"""
Expand All @@ -51,7 +52,7 @@ async def call_with_retry(
except self._supported_errors as error:
failures += 1
await fail(error)
if failures > self._retries:
if self._retries >= 0 and failures > self._retries:
raise error
backoff = self._backoff.compute(failures)
if backoff > 0:
Expand Down
3 changes: 2 additions & 1 deletion redis/retry.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def __init__(
"""
Initialize a `Retry` object with a `Backoff` object
that retries a maximum of `retries` times.
`retries` can be negative to retry forever.
You can specify the types of supported errors which trigger
a retry with the `supported_errors` parameter.
"""
Expand Down Expand Up @@ -46,7 +47,7 @@ def call_with_retry(self, do, fail):
except self._supported_errors as error:
failures += 1
fail(error)
if failures > self._retries:
if self._retries >= 0 and failures > self._retries:
raise error
backoff = self._backoff.compute(failures)
if backoff > 0:
Expand Down
16 changes: 16 additions & 0 deletions tests/test_asyncio/test_retry.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ async def _do(self):
async def _fail(self, error):
self.actual_failures += 1

async def _fail_inf(self, error):
self.actual_failures += 1
if self.actual_failures == 5:
raise ConnectionError()

@pytest.mark.parametrize("retries", range(10))
@pytest.mark.asyncio
async def test_retry(self, retries: int):
Expand All @@ -68,3 +73,14 @@ async def test_retry(self, retries: int):
assert self.actual_failures == 1 + retries
assert backoff.reset_calls == 1
assert backoff.calls == retries

@pytest.mark.asyncio
async def test_infinite_retry(self):
backoff = BackoffMock()
# specify infinite retries, but give up after 5
retry = Retry(backoff, -1)
with pytest.raises(ConnectionError):
await retry.call_with_retry(self._do, self._fail_inf)

assert self.actual_attempts == 5
assert self.actual_failures == 5