Commits

Sylvain Hellegouarch  committed 2f34ac0

redis cache recipe

  • Participants
  • Parent commits 3b5e670

Comments (0)

Files changed (3)

File web/caching/redis_caching/__init__.py

+# -*- coding: utf-8 -*-
+import cherrypy
+
+class Root(object):
+    @cherrypy.expose
+    def index(self):
+        counter = int(cherrypy.request.cache['count'])
+        counter += 1
+        cherrypy.request.cache['count'] = counter
+        return """<html>
+<head />
+<body>
+    <a href="/">Hit me again</a>
+    <p>Cached value: %d</p>
+</body>
+</html>""" % counter
+    
+if __name__ == '__main__':
+    cherrypy.config.update({'server.socket_port': 8090})
+    
+    from redisplugin import RedisPlugin
+    RedisPlugin(cherrypy.engine).subscribe()
+
+    from redistool import RedisTool
+    cherrypy.tools.rediscache = RedisTool()
+
+    cherrypy.quickstart(Root(), '', {'/': {'tools.rediscache.on': True,
+                                           'tools.rediscache.keys': {'count': 0}}})

File web/caching/redis_caching/redisplugin.py

+# -*- coding: utf-8 -*-
+import cherrypy
+from cherrypy.process import plugins
+import redis
+
+__all__ = ['RedisPlugin']
+
+class RedisPlugin(plugins.SimplePlugin):
+    def __init__(self, bus, host='127.0.0.1', port=6379):
+        plugins.SimplePlugin.__init__(self, bus)
+        self.client = redis.StrictRedis(host=host, port=port, db=0)
+
+    def start(self):
+        """ Add the channels dedicated to the
+        caching API to the bus.
+        """
+        self.bus.log('Setting up the redis client')
+        self.bus.subscribe("cache-value", self.cache)
+        self.bus.subscribe("get-cached-value", self.get)
+        self.bus.subscribe("del-cached-value", self.delete)
+
+    def stop(self):
+        """ Remove the channels dedicated to the
+        caching API from the bus.
+        """
+        self.bus.log('Releasing the redis client')
+        self.bus.unsubscribe("cache-value", self.cache)
+        self.bus.unsubscribe("get-cached-value", self.get)
+        self.bus.unsubscribe("del-cached-value", self.delete)
+        self.client = None
+
+    def cache(self, key, value):
+        self.client.set(key, value)
+
+    def get(self, key):
+        return self.client.get(key)
+
+    def delete(self, key):
+        return self.client.delete(key)

File web/caching/redis_caching/redistool.py

+# -*- coding: utf-8 -*-
+import cherrypy
+
+__all__ = ['RedisTool']
+
+class RedisTool(cherrypy.Tool):
+    def __init__(self):
+        """ Tool that use a redis cluster as a caching
+        backend for requests to use.
+
+        Enable this tool and provide for each path
+        a suitable set of keys you want to lookup
+        from the cache on each request. These values
+        will be stored into ``cherrypy.request.cache``
+        as a dictionary and available within your
+        page handler. Once the request completes,
+        the values found in ``cherrypy.request.cache``
+        are stored back into the cache.        
+        """
+        cherrypy.Tool.__init__(self, 'before_handler',
+                               self._load_from_cache,
+                               priority=10)
+
+    def _setup(self):
+        cherrypy.Tool._setup(self)
+        cherrypy.request.hooks.attach('before_finalize',
+                                      self._cache_values,
+                                      priority=80)
+ 
+    def _load_from_cache(self, keys):
+        """ Load the given ``keys`` from the cache
+        right before the page handler is called.
+        ``keys`` is a dictionary which provides the
+        default value to use if the cache doesn't hold
+        a given key.
+
+        The cached values are then stored into
+        ``cherrypy.request.cache`` as a dictionary.
+        """
+        values = {}
+        cache = cherrypy.engine.publish
+        for k in keys:
+            v = cache('get-cached-value', k)
+            if v is not []:
+                v = v.pop()
+            if v is None:
+                v = keys[k]
+            values[k] = v
+            
+        cherrypy.request.cache = values
+
+    def _cache_values(self):
+        """ Store the dictionary from
+        ``cherrypy.request.cache`` into the cache
+        every time a request finishes.
+        """
+        try:
+            values = cherrypy.request.cache
+            cache = cherrypy.engine.publish
+            for k in values:
+                cache('cache-value', k, values[k])
+        finally:
+            cherrypy.request.cache = None
+            delattr(cherrypy.request, 'cache')