changeset 1018:78af5457d3f8

Pages: added url_cache setting: when url_cache is set, result of parse_url is cached (per profile, because in some pages date retrieved may differ between profiles), and then reused. This is useful if some data are fetched during parse_url (e.g. bridge/XMPP call).
author Goffi <goffi@goffi.org>
date Sun, 21 Jan 2018 13:08:54 +0100
parents 8e7897b1008a
children 34240d08f682
files src/server/pages.py
diffstat 1 files changed, 56 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/server/pages.py	Fri Jan 19 18:14:28 2018 +0100
+++ b/src/server/pages.py	Sun Jan 21 13:08:54 2018 +0100
@@ -42,12 +42,12 @@
 WebsocketMeta = namedtuple("WebsocketMeta", ('url', 'token', 'debug'))
 
 
-class Cache(object):
 
-    def __init__(self, rendered):
+class CacheBase(object):
+
+    def __init__(self):
         self._created = time.time()
         self._last_access = self._created
-        self._rendered = rendered
 
     @property
     def created(self):
@@ -61,11 +61,42 @@
     def last_access(self, timestamp):
         self._last_access = timestamp
 
+
+class CachePage(CacheBase):
+
+    def __init__(self, rendered):
+        super(CachePage, self).__init__()
+        self._created = time.time()
+        self._last_access = self._created
+        self._rendered = rendered
+
     @property
     def rendered(self):
         return self._rendered
 
 
+
+class CacheURL(CacheBase):
+
+    def __init__(self, request):
+        super(CacheURL, self).__init__()
+        try:
+            self._data = request.data.copy()
+        except AttributeError:
+            self._data = {}
+        self._template_data = request.template_data.copy()
+        self._prepath = request.prepath[:]
+        self._postpath = request.postpath[:]
+        del self._template_data['csrf_token']
+
+    def use(self, request):
+        self.last_access = time.time()
+        request.data = self._data.copy()
+        request.template_data.update(self._template_data)
+        request.prepath = self._prepath[:]
+        request.postpath = self._postpath[:]
+
+
 class LiberviaPage(web_resource.Resource):
     isLeaf = True  # we handle subpages ourself
     named_pages = {}
@@ -73,6 +104,7 @@
     signals_handlers = {}
     pages_redirects = {}
     cache = {}
+    cached_urls = {}
     # Set of tuples (service/node/sub_id) of nodes subscribed for caching
     # sub_id can be empty string if not handled by service
     cache_pubsub_sub = set()
@@ -80,7 +112,8 @@
 
     def __init__(self, host, root_dir, url, name=None, redirect=None, access=None, dynamic=False, parse_url=None,
                  prepare_render=None, render=None, template=None,
-                 on_data_post=None, on_data=None, on_signal=None):
+                 on_data_post=None, on_data=None, on_signal=None,
+                 url_cache=False):
         """initiate LiberviaPages
 
         LiberviaPages are the main resources of Libervia, using easy to set python files
@@ -159,6 +192,7 @@
         self.on_data_post = on_data_post
         self.on_data = on_data
         self.on_signal = on_signal
+        self.url_cache = url_cache
         if access == C.PAGES_ACCESS_NONE:
             # none pages just return a 404, no further check is needed
             return
@@ -222,6 +256,7 @@
                     on_data_post=page_data.get('on_data_post'),
                     on_data=page_data.get('on_data'),
                     on_signal=page_data.get('on_signal'),
+                    url_cache=page_data.get('url_cache', False),
                     )
                 parent.putChild(d, resource)
                 log.info(u"Added /{path} page".format(path=u'[...]/'.join(new_path)))
@@ -516,6 +551,9 @@
         request.finish()
         raise failure.Failure(exceptions.CancelError(u'cache is used'))
 
+    def _cacheURL(self, dummy, request, profile):
+        self.cached_urls.setdefault(profile, {})[request.uri] = CacheURL(request)
+
     @classmethod
     def onNodeEvent(cls, host, service, node, event_type, items, profile):
         """Invalidate cache for all pages linked to this node"""
@@ -972,7 +1010,20 @@
             d.addCallback(lambda dummy: self.pageRedirect(self.redirect, request, skip_parse_url=False))
 
         if self.parse_url is not None and not skip_parse_url:
-            d.addCallback(self.parse_url, request)
+            if self.url_cache:
+                profile = self.getProfile(request)
+                try:
+                    cache_url = self.cached_urls[profile][request.uri]
+                except KeyError:
+                    # no cache for this URI yet
+                    # we do normal URL parsing, and then the cache
+                    d.addCallback(self.parse_url, request)
+                    d.addCallback(self._cacheURL, request, profile)
+                else:
+                    log.debug(_(u"using URI cache for {page}").format(page=self))
+                    cache_url.use(request)
+            else:
+                d.addCallback(self.parse_url, request)
 
         d.addCallback(self._subpagesHandler, request)