From 0a7c3bf46b2c33f5e469debc018cea79b025c632 Mon Sep 17 00:00:00 2001 From: Davanum Srinivas Date: Sat, 22 Aug 2015 22:17:26 -0400 Subject: [PATCH] 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 --- oslo_cache/backends/dictionary.py | 24 +++++++++++++++++++++++- oslo_cache/tests/test_dict_backend.py | 21 +++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/oslo_cache/backends/dictionary.py b/oslo_cache/backends/dictionary.py index dd845bbb..352b63d3 100644 --- a/oslo_cache/backends/dictionary.py +++ b/oslo_cache/backends/dictionary.py @@ -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() diff --git a/oslo_cache/tests/test_dict_backend.py b/oslo_cache/tests/test_dict_backend.py index 4b2fe75c..be3ddb1a 100644 --- a/oslo_cache/tests/test_dict_backend.py +++ b/oslo_cache/tests/test_dict_backend.py @@ -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')