Skip to content

Commit

Permalink
Handling of legacy resource registries Products.ResourceRegistries re…
Browse files Browse the repository at this point in the history
…moved

no conditional handling
  • Loading branch information
ksuess committed Feb 5, 2019
1 parent 13d89df commit b18dedb
Show file tree
Hide file tree
Showing 14 changed files with 17 additions and 144 deletions.
2 changes: 1 addition & 1 deletion CHANGES.rst
Expand Up @@ -20,7 +20,7 @@ Bug fixes:
Clean-up

- Legacy code clean-up
Old type resource registry Products.ResourceRegistries made optional
Handling of legacy resource registries Products.ResourceRegistries removed
[ksuess]


Expand Down
10 changes: 2 additions & 8 deletions docs/caching-proxies.rst
Expand Up @@ -22,12 +22,7 @@ returned to a user, because the cache has not been updated since the item
was modified. There are three general strategies for dealing with this:

* Since resources are cached in the proxy based on their URL, you can
"invalidate" the cached copy by changing an item's URL when it is updated.
This is the approach taken by Plone's ResourceRegistries (``portal_css``,
``portal_javascript`` & co): in production mode, the links that are inserted
into Plone's content pages for resource managed by ResourceRegistries
contain a time-based token, which changes when the ResourceRegistries
are updated. This approach has the benefit of also being able to
"invalidate" the cached copy by changing an item's URL when it is updated. This approach has the benefit of also being able to
"invalidate" content stored in a user's browser cache.

* All caching proxies support setting timeouts. This means that content may
Expand Down Expand Up @@ -90,8 +85,7 @@ The default purge paths include:
``Image`` types.

Files and images created (or customised) in the ZMI are purged automatically
when modified. Files managed through the ResourceRegistries do not need
purging, since they have "stable" URLs. To purge Plone content when modified
when modified. To purge Plone content when modified
(or removed), you must select the content types in the control panel. By
default, only the ``File`` and ``Image`` types are purged.

Expand Down
5 changes: 0 additions & 5 deletions docs/etags.rst
Expand Up @@ -42,11 +42,6 @@ The ETag names tokens supported by default are:
* skin
The name of the current skin (theme)

* resourceRegistries
A timestamp indicating the most recent last-modified date for all three
Resource Registries. This is useful for avoiding requests for expired
resources from cached pages.

It is possible to provide additional tokens by registering an ``IETagValue``
adapter. This should be a named adapter on the published object (typically a
view, file resource or Zope page template object) and request, with a unique
Expand Down
7 changes: 0 additions & 7 deletions plone/app/caching/caching.zcml
Expand Up @@ -100,13 +100,6 @@
<!-- Zope resources (including those in resource directories) -->
<cache:ruleset ruleset="plone.resource" for="zope.browserresource.interfaces.IResource" />

<!-- Resources cooked in ResourceRegistries -->
<configure zcml:condition="installed Products.ResourceRegistries">

<cache:ruleset ruleset="plone.stableResource" for="Products.ResourceRegistries.interfaces.ICookedFile" />

</configure>

<!-- Standard Plone (non-blob) file and image content objects -->
<configure zcml:condition="installed Products.ATContentTypes">

Expand Down
2 changes: 0 additions & 2 deletions plone/app/caching/configure.zcml
Expand Up @@ -61,7 +61,5 @@
<adapter factory=".lastmodified.CatalogableDublinCoreLastModified" />
<adapter factory=".lastmodified.DCTimesLastModified" />
<adapter factory=".lastmodified.ResourceLastModified" />
<adapter zcml:condition="installed some.package"
factory=".lastmodified.CookedFileLastModified" />

</configure>
31 changes: 0 additions & 31 deletions plone/app/caching/lastmodified.py
Expand Up @@ -14,13 +14,6 @@
from zope.interface import Interface
from zope.pagetemplate.interfaces import IPageTemplate

# BBB resource registry of old type
try:
from Products.ResourceRegistries.interfaces import ICookedFile
from Products.ResourceRegistries.interfaces import IResourceRegistry
HAVE_RESOURCE_REGISTRIES = True
except ImportError:
HAVE_RESOURCE_REGISTRIES = False

try:
from zope.dublincore.interfaces import IDCTimes
Expand Down Expand Up @@ -158,27 +151,3 @@ def __call__(self):
lmt = getattr(self.context.context, 'lmt', None)
if lmt is not None:
return datetime.fromtimestamp(lmt, tzlocal())


if HAVE_RESOURCE_REGISTRIES:

@implementer(ILastModified)
@adapter(ICookedFile)
class CookedFileLastModified(object):
"""ILastModified for Resource Registry `cooked` files
"""

def __init__(self, context):
self.context = context

def __call__(self):
registry = getContext(self.context, IResourceRegistry)
if (
registry is None or
registry.getDebugMode() or
not registry.isCacheable(self.context.__name__)
):
return None
mtime = getattr(registry.aq_base, '_p_mtime', None)
if mtime is not None and mtime > 0:
return datetime.fromtimestamp(mtime, tzlocal())
1 change: 0 additions & 1 deletion plone/app/caching/operations/configure.zcml
Expand Up @@ -45,7 +45,6 @@
<adapter factory=".etags.CatalogCounter" name="catalogCounter" />
<adapter factory=".etags.ObjectLocked" name="locked" />
<adapter factory=".etags.Skin" name="skin" />
<adapter factory=".etags.ResourceRegistries" name="resourceRegistries" />
<adapter factory=".etags.AnonymousOrRandom" name="anonymousOrRandom" />
<adapter factory=".etags.CopyCookie" name="copy" />

Expand Down
37 changes: 0 additions & 37 deletions plone/app/caching/operations/default.py
Expand Up @@ -26,14 +26,6 @@
import time


try:
from Products.ResourceRegistries.interfaces import ICookedFile
from Products.ResourceRegistries.interfaces import IResourceRegistry
HAVE_RESOURCE_REGISTRIES = True
except ImportError:
HAVE_RESOURCE_REGISTRIES = False


@implementer(ICachingOperation)
@provider(ICachingOperationType)
@adapter(Interface, Interface)
Expand Down Expand Up @@ -299,35 +291,6 @@ class StrongCaching(BaseCaching):
lastModified = ramCache = anonOnly = False


if HAVE_RESOURCE_REGISTRIES:

@adapter(ICookedFile, IHTTPRequest)
class ResourceRegistriesCaching(StrongCaching):
"""Override for StrongCaching which checks ResourceRegistries
cacheability
"""

def interceptResponse(self, rulename, response):
return super(
ResourceRegistriesCaching,
self,
).interceptResponse(rulename, response, class_=StrongCaching)

def modifyResponse(self, rulename, response):
registry = getContext(self.published, IResourceRegistry)

if registry is not None:
if (
registry.getDebugMode() or
not registry.isCacheable(self.published.__name__)
):
doNotCache(self.published, self.request, response)
return

super(ResourceRegistriesCaching, self).modifyResponse(
rulename, response, class_=StrongCaching)


@implementer(ICachingOperation)
@provider(ICachingOperationType)
@adapter(Interface, IHTTPRequest)
Expand Down
32 changes: 0 additions & 32 deletions plone/app/caching/operations/etags.py
Expand Up @@ -182,38 +182,6 @@ def __call__(self):
return portal_skins.getDefaultSkin()


@implementer(IETagValue)
@adapter(Interface, Interface)
class ResourceRegistries(object):
"""The ``resourceRegistries`` etag component, returning the most recent
last modified timestamp from all three Resource Registries. This is
useful for avoiding requests for expired resources from cached pages.
"""

def __init__(self, published, request):
self.published = published
self.request = request

def __call__(self):
context = getContext(self.published)

registries = []
registries.append(getToolByName(context, 'portal_css', None))
registries.append(getToolByName(context, 'portal_javascripts', None))
registries.append(getToolByName(context, 'portal_kss', None))

mtimes = []
now = time.time()
for registry in registries:
mtime = now
if registry is not None:
mtime = getattr(registry.aq_base, '_p_mtime', now)
mtimes.append(mtime)

mtimes.sort()
return str(mtimes[-1])


@implementer(IETagValue)
@adapter(Interface, Interface)
class AnonymousOrRandom(object):
Expand Down
Expand Up @@ -21,7 +21,6 @@
<element>userLanguage</element>
<element>skin</element>
<element>locked</element>
<element>resourceRegistries</element>
</value>
</record>
<record name="plone.app.caching.moderateCaching.plone.content.itemView.ramCache">
Expand Down Expand Up @@ -49,7 +48,6 @@
<element>skin</element>
<element>locked</element>
<element>copy</element>
<element>resourceRegistries</element>
</value>
</record>
<record name="plone.app.caching.moderateCaching.plone.content.folderView.ramCache">
Expand Down Expand Up @@ -119,4 +117,4 @@
</record>


</registry>
</registry>
2 changes: 0 additions & 2 deletions plone/app/caching/profiles/with-caching-proxy/registry.xml
Expand Up @@ -21,7 +21,6 @@
<element>userLanguage</element>
<element>skin</element>
<element>locked</element>
<element>resourceRegistries</element>
</value>
</record>
<record name="plone.app.caching.weakCaching.plone.content.itemView.ramCache">
Expand All @@ -40,7 +39,6 @@
<element>skin</element>
<element>locked</element>
<element>copy</element>
<element>resourceRegistries</element>
</value>
</record>
<record name="plone.app.caching.weakCaching.plone.content.folderView.ramCache">
Expand Down
Expand Up @@ -21,7 +21,6 @@
<element>userLanguage</element>
<element>skin</element>
<element>locked</element>
<element>resourceRegistries</element>
</value>
</record>
<record name="plone.app.caching.weakCaching.plone.content.itemView.ramCache">
Expand All @@ -40,7 +39,6 @@
<element>skin</element>
<element>locked</element>
<element>copy</element>
<element>resourceRegistries</element>
</value>
</record>
<record name="plone.app.caching.weakCaching.plone.content.folderView.ramCache">
Expand Down Expand Up @@ -94,4 +92,4 @@
</record>


</registry>
</registry>
12 changes: 6 additions & 6 deletions plone/app/caching/tests/test_profile_with_caching_proxy.py
Expand Up @@ -147,7 +147,7 @@ def test_composite_viewsxx(self):
# This should use cacheInBrowser
self.assertEqual('max-age=0, must-revalidate, private',
browser.headers['Cache-Control'])
self.assertEqual('"|test_user_1_|%d|en|%s|0|0' % (catalog.getCounter(
self.assertEqual('"|test_user_1_|%d|en|%s|0' % (catalog.getCounter(
), skins_tool.default_skin), _normalize_etag(browser.headers['ETag']))
self.assertGreater(now, dateutil.parser.parse(
browser.headers['Expires']))
Expand All @@ -162,7 +162,7 @@ def test_composite_viewsxx(self):
browser.headers['X-Cache-Operation'])
self.assertEqual('max-age=0, must-revalidate, private',
browser.headers['Cache-Control'])
self.assertEqual('"|test_user_1_|%d|en|%s|0|1' % (catalog.getCounter(
self.assertEqual('"|test_user_1_|%d|en|%s|0' % (catalog.getCounter(
), skins_tool.default_skin), _normalize_etag(browser.headers['ETag']))

# Request the authenticated page
Expand All @@ -181,7 +181,7 @@ def test_composite_viewsxx(self):
# This should use cacheInBrowser
self.assertEqual('max-age=0, must-revalidate, private',
browser.headers['Cache-Control'])
self.assertEqual('"|test_user_1_|%d|en|%s|0' % (catalog.getCounter(
self.assertEqual('"|test_user_1_|%d|en|%s' % (catalog.getCounter(
), skins_tool.default_skin), _normalize_etag(browser.headers['ETag']))
self.assertGreater(now, dateutil.parser.parse(
browser.headers['Expires']))
Expand Down Expand Up @@ -227,7 +227,7 @@ def test_composite_viewsxx(self):
# This should use cacheInBrowser
self.assertEqual('max-age=0, must-revalidate, private',
browser.headers['Cache-Control'])
self.assertEqual('"||%d|en|%s|0|0' % (catalog.getCounter(
self.assertEqual('"||%d|en|%s|0' % (catalog.getCounter(
), skins_tool.default_skin), _normalize_etag(browser.headers['ETag']))
self.assertGreater(now, dateutil.parser.parse(
browser.headers['Expires']))
Expand All @@ -244,7 +244,7 @@ def test_composite_viewsxx(self):
# This should use cacheInBrowser
self.assertEqual('max-age=0, must-revalidate, private',
browser.headers['Cache-Control'])
self.assertEqual('"||%d|en|%s|0' % (catalog.getCounter(
self.assertEqual('"||%d|en|%s' % (catalog.getCounter(
), skins_tool.default_skin), _normalize_etag(browser.headers['ETag']))
self.assertGreater(now, dateutil.parser.parse(
browser.headers['Expires']))
Expand All @@ -264,7 +264,7 @@ def test_composite_viewsxx(self):
self.assertIn(testText, browser.contents)
self.assertEqual('max-age=0, must-revalidate, private',
browser.headers['Cache-Control'])
self.assertEqual('"||%d|en|%s|0' % (catalog.getCounter(
self.assertEqual('"||%d|en|%s' % (catalog.getCounter(
), skins_tool.default_skin), _normalize_etag(browser.headers['ETag']))
self.assertGreater(now, dateutil.parser.parse(
browser.headers['Expires']))
Expand Down
12 changes: 6 additions & 6 deletions plone/app/caching/tests/test_profile_without_caching_proxy.py
Expand Up @@ -135,7 +135,7 @@ def test_composite_views(self):
# This should use cacheInBrowser
self.assertEqual('max-age=0, must-revalidate, private',
browser.headers['Cache-Control'])
tag = '"|test_user_1_|{0}|en|{1}|0|0'.format(
tag = '"|test_user_1_|{0}|en|{1}|0'.format(
catalog.getCounter(),
default_skin,
)
Expand All @@ -153,7 +153,7 @@ def test_composite_views(self):
browser.headers['X-Cache-Operation'])
self.assertEqual('max-age=0, must-revalidate, private',
browser.headers['Cache-Control'])
tag = '"|test_user_1_|{0}|en|{1}|0|1'.format(
tag = '"|test_user_1_|{0}|en|{1}|0'.format(
catalog.getCounter(),
default_skin,
)
Expand All @@ -175,7 +175,7 @@ def test_composite_views(self):
# This should use cacheInBrowser
self.assertEqual('max-age=0, must-revalidate, private',
browser.headers['Cache-Control'])
tag = '"|test_user_1_|{0}|en|{1}|0'.format(
tag = '"|test_user_1_|{0}|en|{1}'.format(
catalog.getCounter(),
default_skin,
)
Expand Down Expand Up @@ -223,7 +223,7 @@ def test_composite_views(self):
# This should use cacheInBrowser
self.assertEqual('max-age=0, must-revalidate, private',
browser.headers['Cache-Control'])
tag = '"||{0}|en|{1}|0|0'.format(catalog.getCounter(), default_skin)
tag = '"||{0}|en|{1}|0'.format(catalog.getCounter(), default_skin)
self.assertEqual(tag, _normalize_etag(browser.headers['ETag']))
self.assertGreater(now, dateutil.parser.parse(
browser.headers['Expires']))
Expand All @@ -240,7 +240,7 @@ def test_composite_views(self):
# This should use cacheInBrowser
self.assertEqual('max-age=0, must-revalidate, private',
browser.headers['Cache-Control'])
tag = '"||{0}|en|{1}|0'.format(catalog.getCounter(), default_skin)
tag = '"||{0}|en|{1}'.format(catalog.getCounter(), default_skin)
self.assertEqual(tag, _normalize_etag(browser.headers['ETag']))
self.assertGreater(now, dateutil.parser.parse(
browser.headers['Expires']))
Expand All @@ -260,7 +260,7 @@ def test_composite_views(self):
self.assertIn(testText, browser.contents)
self.assertEqual('max-age=0, must-revalidate, private',
browser.headers['Cache-Control'])
tag = '"||{0}|en|{1}|0'.format(catalog.getCounter(), default_skin)
tag = '"||{0}|en|{1}'.format(catalog.getCounter(), default_skin)
self.assertEqual(tag, _normalize_etag(browser.headers['ETag']))
self.assertGreater(now, dateutil.parser.parse(
browser.headers['Expires']))
Expand Down

1 comment on commit b18dedb

@jenkins-plone-org
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ksuess Jenkins CI reporting about code analysis
See the full report here: https://jenkins.plone.org/job/package-plone.app.caching/60/violations

plone/app/caching/lookup.py:57:5: C901 'ContentItemLookup.__call__' is too complex (12)
plone/app/caching/purge.py:182:5: C901 'ScalesPurgePaths.getRelativePaths' is too complex (12)
plone/app/caching/testing.py:49:9: D001 found xmlconfig.file( replace it with self.loadZCML(
plone/app/caching/utils.py:63:11: T000 Todo note found.
plone/app/caching/browser/controlpanel.py:31:1: I001 isort found an import in the wrong position
plone/app/caching/browser/controlpanel.py:39:12: C812 missing trailing comma
plone/app/caching/browser/controlpanel.py:90:5: C901 'ControlPanel.publishTraverse' is too complex (11)
plone/app/caching/browser/controlpanel.py:172:5: C901 'ControlPanel.processSave' is too complex (34)
plone/app/caching/browser/controlpanel.py:439:45: E231 missing whitespace after ':'
plone/app/caching/browser/controlpanel.py:439:80: E501 line too long (85 > 79 characters)
plone/app/caching/browser/controlpanel.py:568:5: C901 'Purge.processPurge' is too complex (19)
plone/app/caching/browser/edit.py:208:11: T000 Todo note found.
plone/app/caching/browser/edit.py:271:21: C812 missing trailing comma
plone/app/caching/operations/default.py:68:59: C812 missing trailing comma
plone/app/caching/operations/default.py:129:32: C815 missing trailing comma in Python 3.5+
plone/app/caching/operations/default.py:134:5: C901 'BaseCaching.modifyResponse' is too complex (11)
plone/app/caching/operations/default.py:167:15: T000 Todo note found.
plone/app/caching/operations/default.py:226:51: C812 missing trailing comma
plone/app/caching/operations/default.py:279:58: C812 missing trailing comma
plone/app/caching/operations/utils.py:362:1: C901 'isModified' is too complex (14)
plone/app/caching/operations/utils.py:434:7: T000 Todo note found.
plone/app/caching/tests/test_profile_with_caching_proxy.py:150:26: S001 found module formatter
plone/app/caching/tests/test_profile_with_caching_proxy.py:165:26: S001 found module formatter
plone/app/caching/tests/test_profile_with_caching_proxy.py:184:26: S001 found module formatter
plone/app/caching/tests/test_profile_with_caching_proxy.py:230:26: S001 found module formatter
plone/app/caching/tests/test_profile_with_caching_proxy.py:247:26: S001 found module formatter
plone/app/caching/tests/test_profile_with_caching_proxy.py:267:26: S001 found module formatter
plone/app/caching/tests/test_profile_without_caching_proxy.py:15:1: F401 'Products.CMFCore.FSFile.FSFile' imported but unused
plone/app/caching/tests/test_purge.py:43:1: I003 isort expected 1 blank line in imports, found 0

Follow these instructions to reproduce it locally.

Please sign in to comment.