Commits

Andriy Kornatskyy committed ae3f0df

Added delete_multi to cache dependency.

Comments (0)

Files changed (2)

src/wheezy/caching/dependency.py

         return self.cache.add_multi(mapping, self.time, '', self.namespace)
 
     def delete(self, master_key):
-        """ Delete all items wired by this cache dependency.
+        """ Delete all items wired by *master_key* cache dependency.
         """
         cache = self.cache
         n = cache.get(master_key, self.namespace)
         keys.extend(itervalues(cache.get_multi(keys, '', self.namespace)))
         keys.append(master_key)
         return cache.delete_multi(keys, 0, '', self.namespace)
+
+    def delete_multi(self, master_keys):
+        """ Delete all items wired by *master_keys* cache dependencies.
+        """
+        cache = self.cache
+        numbers = cache.get_multi(master_keys, '', self.namespace)
+        if not numbers:
+            return True
+        keys = [master_key + str(i) for master_key, n in numbers.items()
+                for i in xrange(1, n + 1)]
+        keys.extend(itervalues(cache.get_multi(keys, '', self.namespace)))
+        keys.extend(master_keys)
+        return cache.delete_multi(keys, 0, '', self.namespace)

src/wheezy/caching/tests/test_dependency.py

         assert self.d.delete('key')
         self.mock_cache.get.assert_called_once_with(
             'key', 'ns')
-
-        self.mock_cache.reset_mock()
-        self.mock_cache.get.return_value = None
-        assert self.d.delete('key')
-        self.mock_cache.get.assert_called_once_with(
-            'key', 'ns')
+        assert not self.mock_cache.get_multi.called
+        assert not self.mock_cache.delete_multi.called
 
         def side_effect(*args):
             assert ['key1', 'key2'] == args[0]
             ANY, 0, '', 'ns')
         assert ['k1', 'k2', 'key', 'key1', 'key2'] == sorted(
             self.mock_cache.delete_multi.call_args[0][0])
+
+    def test_delete_multi(self):
+        """ Ensure related keys are invalidated for multi
+            dependencies.
+        """
+        self.mock_cache.get_multi.return_value = None
+        assert self.d.delete_multi(['ka', 'kb'])
+        self.mock_cache.get_multi.assert_called_once_with(
+            ['ka', 'kb'], '', 'ns')
+        assert not self.mock_cache.delete_multi.called
+
+        calls = [
+            {'ka': 2, 'kb': 1},
+            {'ka1': 'k1', 'ka2': 'k2', 'kb1': 'k3'}
+        ]
+
+        def side_effect(*args):
+            result = calls[0]
+            del calls[0]
+            return result
+        self.mock_cache.reset_mock()
+        self.mock_cache.get_multi.side_effect = side_effect
+
+        assert self.d.delete_multi(['ka', 'kb', 'kc'])
+        assert 2 == self.mock_cache.get_multi.call_count
+        self.mock_cache.delete_multi.assert_called_once_with(
+            ANY, 0, '', 'ns')
+        assert ['k1', 'k2', 'k3', 'ka', 'ka1', 'ka2', 'kb', 'kb1', 'kc'
+                ] == sorted(self.mock_cache.delete_multi.call_args[0][0])