Commit 54638d40 authored by Sean Bleier's avatar Sean Bleier

Added ability to use redis' incr to increment and decrement values.

To do this, we need to keep integers untouched while pickling any other type
of value. Existing tests should prove that the native incr is working, but
I added a test to show that if an integer was pickled and native incr is used,
then the cache backend will convert the pickled integer correctly.
parent dbcaf532
......@@ -88,7 +88,12 @@ class CacheClass(BaseCache):
value = self._cache.get(key)
if value is None:
return default
return self.unpickle(value)
try:
result = int(value)
except (ValueError, TypeError):
result = self.unpickle(value)
return result
def set(self, key, value, timeout=None, version=None, client=None):
"""
......@@ -97,11 +102,14 @@ class CacheClass(BaseCache):
if not client:
client = self._cache
key = self.make_key(key, version=version)
# get timout
if not timeout:
timeout = self.default_timeout
# store the pickled value
try:
value = int(value)
except (ValueError, TypeError):
result = self._cache.setex(key, pickle.dumps(value), int(timeout))
else:
result = self._cache.setex(key, value, int(timeout))
# result is a boolean
return result
......@@ -165,6 +173,22 @@ class CacheClass(BaseCache):
self.set(key, value, timeout, version=version, client=pipeline)
pipeline.execute()
def incr(self, key, delta=1, version=None):
"""
Add delta to value in the cache. If the key does not exist, raise a
ValueError exception.
"""
key = self.make_key(key, version=version)
exists = self._cache.exists(key)
if not exists:
raise ValueError("Key '%s' not found" % key)
try:
value = self._cache.incr(key, delta)
except redis.ResponseError:
value = self.get(key) + 1
self.set(key, value)
return value
class RedisCache(CacheClass):
"""
......
......@@ -277,6 +277,24 @@ class RedisCacheTests(TestCase):
self.assertEqual(self.cache.get(old_key), None)
self.assertEqual(self.cache.get(new_key), 'spam')
def test_incr_with_pickled_integer(self):
"Testing case where there exists a pickled integer and we increment it"
number = 42
key = self.cache.make_key("key")
# manually set value using the redis client
self.cache._cache.set(key, pickle.dumps(number))
new_value = self.cache.incr(key)
self.assertEqual(new_value, number + 1)
# Test that the pickled value was converted to an integer
value = int(self.cache._cache.get(key))
self.assertTrue(isinstance(value, int))
# now that the value is an integer, let's increment it again.
new_value = self.cache.incr(key, 7)
self.assertEqual(new_value, number + 8)
if __name__ == '__main__':
unittest.main()
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