Unverified Commit ca30ec36 authored by Sean Bleier's avatar Sean Bleier Committed by GitHub

Merge pull request #178 from PoByBolek/get-or-set-with-value

allow to pass a value to get_or_set
parents 19ee8420 b506dd14
......@@ -131,16 +131,18 @@ Cache Methods Provided by django-redis-cache
:param version: Version of the keys
.. function:: get_or_set(self, key, func[, timeout=None, lock_timeout=None, stale_cache_timeout=None]):
.. function:: get_or_set(self, key, default[, timeout=None, lock_timeout=None, stale_cache_timeout=None]):
Get a value from the cache or call ``func`` to set it and return it.
Get a value from the cache or use ``default`` to set it and return it.
If ``default`` is a callable, call it without arguments and store its return value in the cache instead.
This implementation is slightly more advanced that Django's. It provides thundering herd
protection, which prevents multiple threads/processes from calling the value-generating
function at the same time.
:param key: Location of the value
:param func: Callable used to set the value if key does not exist.
:param default: Used to set the value if key does not exist.
:param timeout: Time in seconds that value at key is considered fresh.
:type timeout: Number of seconds or None
:param lock_timeout: Time in seconds that the lock will stay active and prevent other threads from acquiring the lock.
......
......@@ -417,11 +417,13 @@ class BaseRedisCache(BaseCache):
self,
client,
key,
func,
default,
timeout=DEFAULT_TIMEOUT,
lock_timeout=None,
stale_cache_timeout=None):
"""Get a value from the cache or call ``func`` to set it and return it.
"""Get a value from the cache or use ``default`` to set it and return it.
If ``default`` is a callable, call it without arguments and store its return value in the cache instead.
This implementation is slightly more advanced that Django's. It provides thundering herd
protection, which prevents multiple threads/processes from calling the value-generating
......@@ -436,9 +438,6 @@ class BaseRedisCache(BaseCache):
expired. If ``None`` is specified, the stale value will remain indefinitely.
"""
if not callable(func):
raise Exception("Must pass in a callable")
lock_key = "__lock__" + key
fresh_key = "__fresh__" + key
......@@ -455,7 +454,7 @@ class BaseRedisCache(BaseCache):
if acquired:
try:
value = func()
value = default() if callable(default) else default
except Exception:
raise
else:
......
......@@ -8,11 +8,8 @@ class RedisDummyCache(DummyCache):
def delete_pattern(self, pattern, version=None):
return None
def get_or_set(self, key, func, timeout=None):
if not callable(func):
raise Exception("Must pass in a callable")
return func()
def get_or_set(self, key, default, timeout=None):
return default() if callable(default) else default
def reinsert_keys(self):
return None
......
......@@ -486,7 +486,7 @@ class BaseRedisTestCase(SetupMixin):
self.assertEqual(self.cache.get('b'), 'b')
self.assertGreater(self.cache.ttl('a'), 1)
def test_get_or_set(self):
def test_get_or_set_with_callable(self):
def expensive_function():
expensive_function.num_calls += 1
......@@ -511,6 +511,15 @@ class BaseRedisTestCase(SetupMixin):
self.assertEqual(expensive_function.num_calls, 2)
self.assertEqual(value, 42)
def test_get_or_set_with_value(self):
self.assertEqual(self.cache.get_or_set('a', 42, 1), 42)
self.assertEqual(self.cache.get_or_set('a', 43, 1), 42)
self.assertEqual(self.cache.get_or_set('a', 44, 1), 42)
time.sleep(2)
self.assertEqual(self.cache.get_or_set('a', 45, 1), 45)
self.assertEqual(self.cache.get_or_set('a', 46, 1), 45)
self.assertEqual(self.cache.get_or_set('a', 47, 1), 45)
def test_get_or_set_serving_from_stale_value(self):
def expensive_function(x):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment