[Twisted-web] nevow Page caching

Andrea Arcangeli andrea at cpushare.com
Sun Apr 3 07:40:42 MDT 2005


Just as reminder, this is a pending patch against SVN trunk to add an
easy page-wide caching with timeout or persistent.

Index: Nevow/nevow/rend.py
===================================================================
--- Nevow/nevow/rend.py	(revision 1399)
+++ Nevow/nevow/rend.py	(working copy)
@@ -30,6 +30,7 @@
 from nevow import flat
 from nevow.util import log
 from nevow import util
+from nevow import url
 
 import formless
 from formless import iformless
@@ -405,6 +406,8 @@
         self.children[name] = child
     
 
+_CACHE = {}
+
 class Page(Fragment, ConfigurableFactory, ChildLookupMixin):
     """A page is the main Nevow resource and renders a document loaded
     via the document factory (docFactory).
@@ -418,8 +421,37 @@
     afterRender = None
     addSlash = None
 
+    cache = False
+    lifetime = -1
+    __lastCacheRendering = 0
+
     flattenFactory = lambda self, *args: flat.flattenFactory(*args)
 
+    def hasCache(self, ctx):
+        if not self.cache:
+            return
+
+        _now = now() # run gettimeofday only once
+        timeout = _now > self.__lastCacheRendering + self.lifetime and \
+                  self.lifetime >= 0
+        c = self.lookupCache(ctx)
+        if timeout or c is None:
+            # stop other renders
+            self.__lastCacheRendering = _now
+            c = None
+        return c
+    def cacheRendered(self, ctx, c):
+        if not self.cache:
+            return
+        # overwrite the deferred with the data
+        self.storeCache(ctx, c)
+    def cacheIDX(self, ctx):
+        return str(url.URL.fromContext(ctx))
+    def storeCache(self, ctx, c):
+        _CACHE[self.cacheIDX(ctx)] = c
+    def lookupCache(self, ctx):
+        return _CACHE.get(self.cacheIDX(ctx))
+
     def renderHTTP(self, ctx):
         if self.beforeRender is not None:
             return util.maybeDeferred(self.beforeRender,ctx).addCallback(
@@ -444,11 +476,18 @@
             if self.afterRender is not None:
                 return util.maybeDeferred(self.afterRender,ctx)
 
-        if self.buffered:
+        c = self.hasCache(ctx)
+        if c is not None:
+            finishRequest()
+            return c
+
+        if self.buffered or self.cache:
             io = StringIO()
             writer = io.write
             def finisher(result):
-                request.write(io.getvalue())
+                c = io.getvalue()
+                self.cacheRendered(ctx, c)
+                request.write(c)
                 return util.maybeDeferred(finishRequest).addCallback(lambda r: result)
         else:
             writer = request.write
@@ -532,7 +571,6 @@
             else:
                 ## Use the redirectAfterPost url
                 ref = str(redirectAfterPost)
-            from nevow import url
             refpath = url.URL.fromString(ref)
             magicCookie = '%s%s%s' % (now(),request.getClientIP(),random.random())
             refpath = refpath.replace('_nevow_carryover_', magicCookie)



More information about the Twisted-web mailing list