Commits

Mike Bayer  committed 767dd6a

Added a method ``refresh()`` to functions decorated by
:meth:`.CacheRegion.cache_on_arguments` and
:meth:`.CacheRegion.cache_multi_on_arguments`, to complement
``invalidate()`` and ``set()``.
#36

  • Participants
  • Parent commits 6a411a5

Comments (0)

Files changed (3)

File docs/build/changelog.rst

       maintaining dogpile semantics for each.
 
     .. change::
+      :tags: feature
+      :tickets: 36
+
+      Added a method ``refresh()`` to functions decorated by
+      :meth:`.CacheRegion.cache_on_arguments` and
+      :meth:`.CacheRegion.cache_multi_on_arguments`, to complement
+      ``invalidate()`` and ``set()``.
+
+    .. change::
         :tags: feature
         :tickets: 13
 

File dogpile/cache/region.py

 
             result = generate_something(5, 6)
 
-        The function is also given an attribute ``invalidate``, which
+        The function is also given an attribute ``invalidate()``, which
         provides for invalidation of the value.  Pass to ``invalidate()``
         the same arguments you'd pass to the function itself to represent
         a particular value::
 
             generate_something.invalidate(5, 6)
 
-        Another attribute ``set`` is added to provide extra caching
+        Another attribute ``set()`` is added to provide extra caching
         possibilities relative to the function.   This is a convenience
         method for :meth:`.CacheRegion.set` which will store a given
         value directly without calling the decorated function.
         if the function were to produce the value ``3`` as the value to be
         cached.
 
-        .. versionadded:: 0.4.1 Added set() method to decorated function.
+        .. versionadded:: 0.4.1 Added ``set()`` method to decorated function.
+
+        Similar to ``set()`` is ``refresh()``.   This attribute will
+        invoke the decorated function and populate a new value into
+        the cache with the new value, as well as returning that value::
+
+            newvalue = generate_something.refresh(5, 6)
+
+        .. versionadded:: 0.5.0 Added ``refresh()`` method to decorated
+           function.
 
         The default key generation will use the name
         of the function, the module name for the function,
                 key = key_generator(*arg, **kw)
                 self.set(key, value)
 
+            def refresh(*arg, **kw):
+                key = key_generator(*arg, **kw)
+                value = fn(*arg, **kw)
+                self.set(key, value)
+                return value
+
             decorate.set = set_
             decorate.invalidate = invalidate
+            decorate.refresh = refresh
 
             return decorate
         return decorator
             generate_something.set({"k1": "value1",
                                     "k2": "value2", "k3": "value3"})
 
-        as well as an ``invalidate()`` method, which has the effect of deleting
+        an ``invalidate()`` method, which has the effect of deleting
         the given sequence of keys using the same mechanism as that of
         :meth:`.CacheRegion.delete_multi`::
 
             generate_something.invalidate("k1", "k2", "k3")
 
+        and finally a ``refresh()`` method, which will call the creation
+        function, cache the new values, and return them::
+
+            values = generate_something.refresh("k1", "k2", "k3")
+
         Parameters passed to :meth:`.CacheRegion.cache_multi_on_arguments`
         have the same meaning as those passed to
         :meth:`.CacheRegion.cache_on_arguments`.
                         in zip(gen_keys, keys))
                     )
 
+            def refresh(*arg):
+                keys = key_generator(*arg)
+                values = fn(*arg)
+                self.set_multi(
+                            dict(zip(keys, values))
+                        )
+                return values
+
             decorate.set = set_
             decorate.invalidate = invalidate
+            decorate.refresh = refresh
 
             return decorate
         return decorator

File tests/cache/test_decorator.py

     def _fixture(self, namespace=None, expiration_time=None):
         reg = self._region(config_args={"expiration_time":.25})
 
-        counter = [0]
+        counter = itertools.count(1)
         @reg.cache_on_arguments(namespace=namespace,
                             expiration_time=expiration_time)
         def go(a, b):
-            counter[0] +=1
-            return counter[0], a, b
+            val = next(counter)
+            return val, a, b
+        return go
+
+    def _multi_fixture(self, namespace=None, expiration_time=None):
+        reg = self._region(config_args={"expiration_time":.25})
+
+        counter = itertools.count(1)
+        @reg.cache_multi_on_arguments(namespace=namespace,
+                            expiration_time=expiration_time)
+        def go(*args):
+            val = next(counter)
+            return ["%d %s" % (val, arg) for arg in args]
         return go
 
+
     def test_decorator(self):
         go = self._fixture()
         eq_(go(1, 2), (1, 1, 2))
         go.set(0, 1, 3)
         eq_(go(1, 3), 0)
 
+    def test_explicit_set_multi(self):
+        go = self._multi_fixture(expiration_time=1)
+        eq_(go(1, 2), ['1 1', '1 2'])
+        eq_(go(1, 2), ['1 1', '1 2'])
+        go.set({1: '1 5', 2: '1 6'})
+        eq_(go(1, 2), ['1 5', '1 6'])
+
+    def test_explicit_refresh(self):
+        go = self._fixture(expiration_time=1)
+        eq_(go(1, 2), (1, 1, 2))
+        eq_(go.refresh(1, 2), (2, 1, 2))
+        eq_(go(1, 2), (2, 1, 2))
+        eq_(go(1, 2), (2, 1, 2))
+        eq_(go.refresh(1, 2), (3, 1, 2))
+        eq_(go(1, 2), (3, 1, 2))
+
+    def test_explicit_refresh_multi(self):
+        go = self._multi_fixture(expiration_time=1)
+        eq_(go(1, 2), ['1 1', '1 2'])
+        eq_(go(1, 2), ['1 1', '1 2'])
+        eq_(go.refresh(1, 2), ['2 1', '2 2'])
+        eq_(go(1, 2), ['2 1', '2 2'])
+        eq_(go(1, 2), ['2 1', '2 2'])
+
 class KeyGenerationTest(TestCase):
     def _keygen_decorator(self, namespace=None):
         canary = []