Implement get/set/delete multiple keys for dictionary backend

For some Nova scenarios, we will need suppot for
set_multi/get_multi/delete_multi for writing to either
memcache or dictionary backend. So let's add support for
operating on multiple keys. Note that if we don't implement
this the default CacheBackend class throws NotImplementedError

Closes-Bug: #1483322
Change-Id: I1aca9e65b3be038a507ced8dd039c5413d6c4ac2
This commit is contained in:
Davanum Srinivas 2015-08-22 22:17:26 -04:00
parent 72c9267874
commit 0a7c3bf46b
2 changed files with 44 additions and 1 deletions

View File

@ -55,18 +55,32 @@ class DictCacheBackend(api.CacheBackend):
return value
def get_multi(self, keys):
"""Retrieves the value for a list of keys."""
return [self.get(key) for key in keys]
def set(self, key, value):
"""Sets the value for a key.
Expunges expired keys during each set.
:param key: dictionary key
:param value: value associated with the key
"""
self.set_multi({key: value})
def set_multi(self, mapping):
"""Set multiple values in the cache.
Expunges expired keys during each set.
:param mapping: dictionary with key/value pairs
"""
self._clear()
timeout = 0
if self.expiration_time > 0:
timeout = timeutils.utcnow_ts() + self.expiration_time
self.cache[key] = (value, timeout)
for key, value in mapping.items():
self.cache[key] = (value, timeout)
def delete(self, key):
"""Deletes the value associated with the key if it exists.
@ -75,6 +89,14 @@ class DictCacheBackend(api.CacheBackend):
"""
self.cache.pop(key, None)
def delete_multi(self, keys):
"""Deletes the value associated with each key in list if it exists.
:param keys: list of dictionary keys
"""
for key in keys:
self.cache.pop(key, None)
def _clear(self):
"""Expunges expired keys."""
now = timeutils.utcnow_ts()

View File

@ -88,6 +88,27 @@ class CacheDictBackendTest(test_cache.BaseTestCase):
self.assertIs(NO_VALUE, self.region.get('key2'))
self.assertEqual('value3', self.region.get('key3'))
def test_dict_backend_multi_keys_in_one_call(self):
single_value = 'Test Value'
single_key = 'testkey'
multi_values = {'key1': 1, 'key2': 2, 'key3': 3}
self.region.set(single_key, single_value)
self.assertEqual(single_value, self.region.get(single_key))
self.region.delete(single_key)
self.assertEqual(NO_VALUE, self.region.get(single_key))
self.region.set_multi(multi_values)
cached_values = self.region.get_multi(multi_values.keys())
for value in multi_values.values():
self.assertIn(value, cached_values)
self.assertEqual(len(multi_values.values()), len(cached_values))
self.region.delete_multi(multi_values.keys())
for value in self.region.get_multi(multi_values.keys()):
self.assertEqual(NO_VALUE, value)
def test_dict_backend_rewrite_value(self):
self.region.set(KEY, 'value1')
self.region.set(KEY, 'value2')