Skip to content

Commit b506dd1

Browse files
committed
allow to pass a value to get_or_set
fixes issue sebleier#124
1 parent 9382347 commit b506dd1

File tree

4 files changed

+22
-15
lines changed

4 files changed

+22
-15
lines changed

docs/api.rst

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,16 +131,18 @@ Cache Methods Provided by django-redis-cache
131131
:param version: Version of the keys
132132

133133

134-
.. function:: get_or_set(self, key, func[, timeout=None, lock_timeout=None, stale_cache_timeout=None]):
134+
.. function:: get_or_set(self, key, default[, timeout=None, lock_timeout=None, stale_cache_timeout=None]):
135135

136-
Get a value from the cache or call ``func`` to set it and return it.
136+
Get a value from the cache or use ``default`` to set it and return it.
137+
138+
If ``default`` is a callable, call it without arguments and store its return value in the cache instead.
137139

138140
This implementation is slightly more advanced that Django's. It provides thundering herd
139141
protection, which prevents multiple threads/processes from calling the value-generating
140142
function at the same time.
141143

142144
:param key: Location of the value
143-
:param func: Callable used to set the value if key does not exist.
145+
:param default: Used to set the value if key does not exist.
144146
:param timeout: Time in seconds that value at key is considered fresh.
145147
:type timeout: Number of seconds or None
146148
:param lock_timeout: Time in seconds that the lock will stay active and prevent other threads from acquiring the lock.

redis_cache/backends/base.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -410,11 +410,13 @@ def get_or_set(
410410
self,
411411
client,
412412
key,
413-
func,
413+
default,
414414
timeout=DEFAULT_TIMEOUT,
415415
lock_timeout=None,
416416
stale_cache_timeout=None):
417-
"""Get a value from the cache or call ``func`` to set it and return it.
417+
"""Get a value from the cache or use ``default`` to set it and return it.
418+
419+
If ``default`` is a callable, call it without arguments and store its return value in the cache instead.
418420
419421
This implementation is slightly more advanced that Django's. It provides thundering herd
420422
protection, which prevents multiple threads/processes from calling the value-generating
@@ -429,9 +431,6 @@ def get_or_set(
429431
expired. If ``None`` is specified, the stale value will remain indefinitely.
430432
431433
"""
432-
if not callable(func):
433-
raise Exception("Must pass in a callable")
434-
435434
lock_key = "__lock__" + key
436435
fresh_key = "__fresh__" + key
437436

@@ -448,7 +447,7 @@ def get_or_set(
448447

449448
if acquired:
450449
try:
451-
value = func()
450+
value = default() if callable(default) else default
452451
except Exception:
453452
raise
454453
else:

redis_cache/backends/dummy.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,8 @@ def ttl(self, key):
88
def delete_pattern(self, pattern, version=None):
99
return None
1010

11-
def get_or_set(self, key, func, timeout=None):
12-
if not callable(func):
13-
raise Exception("Must pass in a callable")
14-
15-
return func()
11+
def get_or_set(self, key, default, timeout=None):
12+
return default() if callable(default) else default
1613

1714
def reinsert_keys(self):
1815
return None

tests/testapp/tests/base_tests.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ def test_ttl_of_reinsert_keys(self):
486486
self.assertEqual(self.cache.get('b'), 'b')
487487
self.assertGreater(self.cache.ttl('a'), 1)
488488

489-
def test_get_or_set(self):
489+
def test_get_or_set_with_callable(self):
490490

491491
def expensive_function():
492492
expensive_function.num_calls += 1
@@ -511,6 +511,15 @@ def expensive_function():
511511
self.assertEqual(expensive_function.num_calls, 2)
512512
self.assertEqual(value, 42)
513513

514+
def test_get_or_set_with_value(self):
515+
self.assertEqual(self.cache.get_or_set('a', 42, 1), 42)
516+
self.assertEqual(self.cache.get_or_set('a', 43, 1), 42)
517+
self.assertEqual(self.cache.get_or_set('a', 44, 1), 42)
518+
time.sleep(2)
519+
self.assertEqual(self.cache.get_or_set('a', 45, 1), 45)
520+
self.assertEqual(self.cache.get_or_set('a', 46, 1), 45)
521+
self.assertEqual(self.cache.get_or_set('a', 47, 1), 45)
522+
514523
def test_get_or_set_serving_from_stale_value(self):
515524

516525
def expensive_function(x):

0 commit comments

Comments
 (0)