Invalidate cache on settings update
authorThierry Florac <tflorac@ulthar.net>
Thu, 19 Jul 2018 22:15:29 +0200
changeset 868 1fcd5c845d1d
parent 867 17c1149151aa
child 869 ae7f0471e337
Invalidate cache on settings update
src/pyams_content/features/footer/__init__.py
src/pyams_content/features/footer/interfaces/__init__.py
src/pyams_content/features/footer/skin/__init__.py
src/pyams_content/features/header/__init__.py
src/pyams_content/features/header/interfaces/__init__.py
src/pyams_content/features/header/skin/__init__.py
--- a/src/pyams_content/features/footer/__init__.py	Thu Jul 19 17:19:50 2018 +0200
+++ b/src/pyams_content/features/footer/__init__.py	Thu Jul 19 22:15:29 2018 +0200
@@ -18,16 +18,20 @@
 # import interfaces
 from pyams_content.features.footer.interfaces import FOOTER_RENDERERS, IFooterRenderer, IFooterSettings, IFooterTarget, \
     FOOTER_SETTINGS_KEY, IFooterRendererSettings, FOOTER_RENDERER_SETTINGS_KEY
+from zope.lifecycleevent.interfaces import IObjectModifiedEvent
 from zope.traversing.interfaces import ITraversable
 
 # import packages
 from persistent import Persistent
+from pyams_cache.beaker import get_cache
 from pyams_content.features.renderer import RenderedContentMixin
+from pyams_portal.portlet import PORTLETS_CACHE_REGION, PORTLETS_CACHE_NAME
 from pyams_utils.adapter import adapter_config, ContextAdapter, get_annotation_adapter
 from pyams_utils.inherit import BaseInheritInfo, InheritedFieldProperty
 from pyams_utils.request import check_request
 from pyams_utils.traversing import get_parent
 from pyams_utils.vocabulary import vocabulary_config
+from pyramid.events import subscriber
 from zope.interface import implementer, noLongerProvides, alsoProvides
 from zope.location import Location, locate
 from zope.schema.fieldproperty import FieldProperty
@@ -77,6 +81,14 @@
     return get_annotation_adapter(context, FOOTER_SETTINGS_KEY, FooterSettings, name='++footer++')
 
 
+@subscriber(IObjectModifiedEvent, context_selector=IFooterSettings)
+def handle_modified_footer_settings(event):
+    """Clear cache if modified footer settings"""
+    renderer = event.object.get_renderer()
+    portlets_cache = get_cache(PORTLETS_CACHE_REGION, PORTLETS_CACHE_NAME)
+    portlets_cache.remove(renderer.cache_key)
+
+
 @adapter_config(name='footer', context=IFooterTarget, provides=ITraversable)
 class FooterTargetNamespace(ContextAdapter):
     """Footer target '++footer++' namespace traverser"""
--- a/src/pyams_content/features/footer/interfaces/__init__.py	Thu Jul 19 17:19:50 2018 +0200
+++ b/src/pyams_content/features/footer/interfaces/__init__.py	Thu Jul 19 22:15:29 2018 +0200
@@ -54,6 +54,7 @@
 
     name = Attribute("Renderer name")
     settings_key = Attribute("Renderer settings key")
+    cache_key = Attribute("Renderer cache key")
 
 
 class IFooterRendererSettings(IRendererSettings):
--- a/src/pyams_content/features/footer/skin/__init__.py	Thu Jul 19 17:19:50 2018 +0200
+++ b/src/pyams_content/features/footer/skin/__init__.py	Thu Jul 19 22:15:29 2018 +0200
@@ -32,13 +32,18 @@
 from pyams_utils.adapter import adapter_config
 from pyams_utils.traversing import get_parent
 from pyramid.decorator import reify
+from zope.interface import implementer
 
 from pyams_content import _
 
 
+@implementer(IFooterRenderer)
 class BaseFooterRenderer(BaseContentRenderer):
     """Base footer renderer"""
 
+    name = None
+    settings_key = None
+
     @reify
     def settings_target(self):
         context = self.request.annotations.get(DISPLAY_CONTEXT)
@@ -56,24 +61,28 @@
             settings = IFooterSettings(settings.parent)
         return settings.settings
 
+    @reify
+    def cache_key(self):
+        return PORTLETS_CACHE_KEY.format(portlet=self.name,
+                                         context=ICacheKeyValue(self.settings_target),
+                                         lang=self.request.locale_name)
+
     def render(self):
         preview_mode = self.request.annotations.get(PREVIEW_MODE, False)
         if preview_mode:
             return super(BaseFooterRenderer, self).render()
         else:
             portlets_cache = get_cache(PORTLETS_CACHE_REGION, PORTLETS_CACHE_NAME)
-            cache_key = PORTLETS_CACHE_KEY.format(portlet=self.name,
-                                                  context=ICacheKeyValue(self.settings_target),
-                                                  lang=self.request.locale_name)
+            cache_key = self.cache_key
             if self.context is not self.request.context:  # display shared content
                 cache_key = '{0}::shared'.format(cache_key)
             try:
                 result = portlets_cache.get_value(cache_key)
-                logger.debug("Retrieving header content from cache key {0}".format(cache_key))
+                logger.debug("Retrieving footer content from cache key {0}".format(cache_key))
             except KeyError:
                 result = super(BaseFooterRenderer, self).render()
                 portlets_cache.set_value(cache_key, result)
-                logger.debug("Storing header content for cache key {0}".format(cache_key))
+                logger.debug("Storing footer content to cache key {0}".format(cache_key))
             return result
 
 
--- a/src/pyams_content/features/header/__init__.py	Thu Jul 19 17:19:50 2018 +0200
+++ b/src/pyams_content/features/header/__init__.py	Thu Jul 19 22:15:29 2018 +0200
@@ -18,16 +18,20 @@
 # import interfaces
 from pyams_content.features.header.interfaces import HEADER_RENDERERS, IHeaderRenderer, IHeaderSettings, IHeaderTarget, \
     HEADER_SETTINGS_KEY, IHeaderRendererSettings, HEADER_RENDERER_SETTINGS_KEY
+from zope.lifecycleevent.interfaces import IObjectModifiedEvent
 from zope.traversing.interfaces import ITraversable
 
 # import packages
 from persistent import Persistent
+from pyams_cache.beaker import get_cache
 from pyams_content.features.renderer import RenderedContentMixin
+from pyams_portal.portlet import PORTLETS_CACHE_REGION, PORTLETS_CACHE_NAME
 from pyams_utils.adapter import adapter_config, ContextAdapter, get_annotation_adapter
 from pyams_utils.inherit import BaseInheritInfo, InheritedFieldProperty
 from pyams_utils.request import check_request
 from pyams_utils.traversing import get_parent
 from pyams_utils.vocabulary import vocabulary_config
+from pyramid.events import subscriber
 from zope.interface import implementer, noLongerProvides, alsoProvides
 from zope.location import Location, locate
 from zope.schema.fieldproperty import FieldProperty
@@ -77,6 +81,14 @@
     return get_annotation_adapter(context, HEADER_SETTINGS_KEY, HeaderSettings, name='++header++')
 
 
+@subscriber(IObjectModifiedEvent, context_selector=IHeaderSettings)
+def handle_modified_header_settings(event):
+    """Clear cache if modified header settings"""
+    renderer = event.object.get_renderer()
+    portlets_cache = get_cache(PORTLETS_CACHE_REGION, PORTLETS_CACHE_NAME)
+    portlets_cache.remove(renderer.cache_key)
+
+
 @adapter_config(name='header', context=IHeaderTarget, provides=ITraversable)
 class HeaderTargetNamespace(ContextAdapter):
     """Header target '++header++' namespace traverser"""
--- a/src/pyams_content/features/header/interfaces/__init__.py	Thu Jul 19 17:19:50 2018 +0200
+++ b/src/pyams_content/features/header/interfaces/__init__.py	Thu Jul 19 22:15:29 2018 +0200
@@ -54,6 +54,8 @@
 
     name = Attribute("Renderer name")
     settings_key = Attribute("Renderer settings key")
+    cache_key = Attribute("Renderer cache key")
+
 
 
 class IHeaderRendererSettings(IRendererSettings):
--- a/src/pyams_content/features/header/skin/__init__.py	Thu Jul 19 17:19:50 2018 +0200
+++ b/src/pyams_content/features/header/skin/__init__.py	Thu Jul 19 22:15:29 2018 +0200
@@ -33,13 +33,18 @@
 from pyams_utils.adapter import adapter_config
 from pyams_utils.traversing import get_parent
 from pyramid.decorator import reify
+from zope.interface import implementer
 
 from pyams_content import _
 
 
+@implementer(IHeaderRenderer)
 class BaseHeaderRenderer(BaseContentRenderer):
     """Base header renderer"""
 
+    name = None
+    settings_key = None
+
     @reify
     def settings_target(self):
         context = self.request.annotations.get(DISPLAY_CONTEXT)
@@ -57,6 +62,12 @@
             settings = IHeaderSettings(settings.parent)
         return settings.settings
 
+    @reify
+    def cache_key(self):
+        return PORTLETS_CACHE_KEY.format(portlet=self.name,
+                                         context=ICacheKeyValue(self.settings_target),
+                                         lang=self.request.locale_name)
+
     @property
     def main_header_class(self):
         request = self.request
@@ -68,9 +79,7 @@
             return super(BaseHeaderRenderer, self).render()
         else:
             portlets_cache = get_cache(PORTLETS_CACHE_REGION, PORTLETS_CACHE_NAME)
-            cache_key = PORTLETS_CACHE_KEY.format(portlet=self.name,
-                                                  context=ICacheKeyValue(self.settings_target),
-                                                  lang=self.request.locale_name)
+            cache_key = self.cache_key
             if self.context is not self.request.context:  # display shared content
                 cache_key = '{0}::shared'.format(cache_key)
             try:
@@ -79,7 +88,7 @@
             except KeyError:
                 result = super(BaseHeaderRenderer, self).render()
                 portlets_cache.set_value(cache_key, result)
-                logger.debug("Storing header content for cache key {0}".format(cache_key))
+                logger.debug("Storing header content to cache key {0}".format(cache_key))
             return result