Skip to content

Commit 7dcc366

Browse files
committed
omit_exception for generator methods sscan_iter and iter_keys
1 parent 755dfb2 commit 7dcc366

File tree

3 files changed

+49
-15
lines changed

3 files changed

+49
-15
lines changed

django_redis/cache.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,15 @@
1313

1414

1515
def omit_exception(
16-
method: Optional[Callable] = None,
17-
return_value: Optional[Any] = None,
16+
method: Optional[Callable] = None, return_value: Optional[Any] = None, gen=False
1817
):
1918
"""
2019
Simple decorator that intercepts connection
2120
errors and ignores these if settings specify this.
2221
"""
2322

2423
if method is None:
25-
return functools.partial(omit_exception, return_value=return_value)
24+
return functools.partial(omit_exception, return_value=return_value, gen=gen)
2625

2726
@functools.wraps(method)
2827
def _decorator(self, *args, **kwargs):
@@ -36,7 +35,21 @@ def _decorator(self, *args, **kwargs):
3635
return return_value
3736
raise e.__cause__ # noqa: B904
3837

39-
return _decorator
38+
@functools.wraps(method)
39+
def _generator_decorator(self, *args, **kwargs):
40+
try:
41+
yield from method(self, *args, **kwargs)
42+
except ConnectionInterrupted as e:
43+
if self._ignore_exceptions:
44+
if self._log_ignored_exceptions:
45+
self.logger.exception("Exception ignored")
46+
47+
return return_value
48+
raise e.__cause__ # noqa: B904
49+
50+
if not gen:
51+
return _decorator
52+
return _generator_decorator
4053

4154

4255
class RedisCache(BaseCache):
@@ -147,7 +160,7 @@ def has_key(self, *args, **kwargs):
147160
def keys(self, *args, **kwargs):
148161
return self.client.keys(*args, **kwargs)
149162

150-
@omit_exception
163+
@omit_exception(gen=True)
151164
def iter_keys(self, *args, **kwargs):
152165
return self.client.iter_keys(*args, **kwargs)
153166

@@ -243,7 +256,7 @@ def srem(self, *args, **kwargs):
243256
def sscan(self, *args, **kwargs):
244257
return self.client.sscan(*args, **kwargs)
245258

246-
@omit_exception
259+
@omit_exception(gen=True)
247260
def sscan_iter(self, *args, **kwargs):
248261
return self.client.sscan_iter(*args, **kwargs)
249262

django_redis/client/default.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -775,8 +775,11 @@ def iter_keys(
775775
client = self.get_client(write=False)
776776

777777
pattern = self.make_pattern(search, version=version)
778-
for item in client.scan_iter(match=pattern, count=itersize):
779-
yield self.reverse_key(item.decode())
778+
try:
779+
for item in client.scan_iter(match=pattern, count=itersize):
780+
yield self.reverse_key(item.decode())
781+
except _main_exceptions as e:
782+
raise ConnectionInterrupted(connection=client) from e
780783

781784
def keys(
782785
self,
@@ -1054,12 +1057,15 @@ def sscan_iter(
10541057
client = self.get_client(write=False)
10551058

10561059
key = self.make_key(key, version=version)
1057-
for value in client.sscan_iter(
1058-
key,
1059-
match=cast("PatternT", self.encode(match)) if match else None,
1060-
count=count,
1061-
):
1062-
yield self.decode(value)
1060+
try:
1061+
for value in client.sscan_iter(
1062+
key,
1063+
match=cast("PatternT", self.encode(match)) if match else None,
1064+
count=count,
1065+
):
1066+
yield self.decode(value)
1067+
except _main_exceptions as e:
1068+
raise ConnectionInterrupted(connection=client) from e
10631069

10641070
def sunion(
10651071
self,

tests/test_cache_options.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@
33
from typing import cast
44

55
import pytest
6-
from django.core.cache import caches
6+
from django.core.cache import caches, cache as default_cache
77
from pytest import LogCaptureFixture
88
from redis.exceptions import ConnectionError as RedisConnectionError
99

1010
from django_redis.cache import RedisCache
1111
from django_redis.client import ShardClient
1212

13+
iter_methods = {
14+
"iter_keys",
15+
"sscan_iter",
16+
}
17+
1318

1419
def make_key(key: str, prefix: str, version: str) -> str:
1520
return f"{prefix}#{version}#{key}"
@@ -55,6 +60,16 @@ def test_get_django_omit_exceptions(
5560
)
5661

5762

63+
def test_iterator_methods(ignore_exceptions_cache: RedisCache, subtests):
64+
for m in iter_methods:
65+
method = getattr(ignore_exceptions_cache, m)
66+
with subtests.test(method=method):
67+
if isinstance(default_cache.client, ShardClient) and m == "iter_keys":
68+
pytest.skip(f"shard client doesn't support {m}")
69+
for _ in method("abc"):
70+
pass
71+
72+
5873
def test_get_django_omit_exceptions_priority_1(settings):
5974
caches_setting = copy.deepcopy(settings.CACHES)
6075
caches_setting["doesnotexist"]["OPTIONS"]["IGNORE_EXCEPTIONS"] = True

0 commit comments

Comments
 (0)