summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristján Valur Jónsson <sweskman@gmail.com>2022-04-28 11:16:14 +0000
committerGitHub <noreply@github.com>2022-04-28 14:16:14 +0300
commitc29d158c854c659994b6d8704d4b420faaa95bca (patch)
treefe6e5ff9c6d5d611aa907115d8ec5c05581f77d5
parentabd5aeffc5cca02826973ab32e4d43e200eff18e (diff)
downloadredis-py-c29d158c854c659994b6d8704d4b420faaa95bca.tar.gz
`Retry()`: Support negative `retries` value (#2110)
* Support negative `retries` value * Add unit test * Add unittest for blocking api
-rw-r--r--CHANGES1
-rw-r--r--redis/asyncio/retry.py3
-rw-r--r--redis/retry.py3
-rw-r--r--tests/test_asyncio/test_retry.py16
-rw-r--r--tests/test_retry.py15
5 files changed, 36 insertions, 2 deletions
diff --git a/CHANGES b/CHANGES
index 9ca62f0..f954a07 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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
diff --git a/redis/asyncio/retry.py b/redis/asyncio/retry.py
index 284eacc..0934ad0 100644
--- a/redis/asyncio/retry.py
+++ b/redis/asyncio/retry.py
@@ -27,6 +27,7 @@ class Retry:
"""
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.
"""
@@ -51,7 +52,7 @@ class 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:
diff --git a/redis/retry.py b/redis/retry.py
index 3dced35..57be971 100644
--- a/redis/retry.py
+++ b/redis/retry.py
@@ -16,6 +16,7 @@ class Retry:
"""
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.
"""
@@ -46,7 +47,7 @@ class Retry:
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:
diff --git a/tests/test_asyncio/test_retry.py b/tests/test_asyncio/test_retry.py
index e83e001..dee83ba 100644
--- a/tests/test_asyncio/test_retry.py
+++ b/tests/test_asyncio/test_retry.py
@@ -56,6 +56,11 @@ class TestRetry:
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):
@@ -68,3 +73,14 @@ class TestRetry:
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
diff --git a/tests/test_retry.py b/tests/test_retry.py
index 0094787..f844fd0 100644
--- a/tests/test_retry.py
+++ b/tests/test_retry.py
@@ -95,6 +95,11 @@ class TestRetry:
def _fail(self, error):
self.actual_failures += 1
+ def _fail_inf(self, error):
+ self.actual_failures += 1
+ if self.actual_failures == 5:
+ raise ConnectionError()
+
@pytest.mark.parametrize("retries", range(10))
def test_retry(self, retries):
backoff = BackoffMock()
@@ -107,6 +112,16 @@ class TestRetry:
assert backoff.reset_calls == 1
assert backoff.calls == retries
+ def test_infinite_retry(self):
+ backoff = BackoffMock()
+ # specify infinite retries, but give up after 5
+ retry = Retry(backoff, -1)
+ with pytest.raises(ConnectionError):
+ retry.call_with_retry(self._do, self._fail_inf)
+
+ assert self.actual_attempts == 5
+ assert self.actual_failures == 5
+
@pytest.mark.onlynoncluster
class TestRedisClientRetry: