# HG changeset patch # User Goffi # Date 1516536534 -3600 # Node ID 78af5457d3f80ecdffd37e89f8091cdc9068dc80 # Parent 8e7897b1008aa7b38b24dd5c978b3dc932d1d12f 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). diff -r 8e7897b1008a -r 78af5457d3f8 src/server/pages.py --- 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)