From 390d3326e64a122d44086f25667e04905a82b825 Mon Sep 17 00:00:00 2001 From: Mauro Amico Date: Tue, 7 Nov 2023 18:30:45 +0100 Subject: [PATCH 1/2] cache transforms --- src/redturtle/volto/overrides.py | 99 ++++++++++++++++++++++++++++++ src/redturtle/volto/overrides.zcml | 14 +++++ 2 files changed, 113 insertions(+) create mode 100644 src/redturtle/volto/overrides.py create mode 100644 src/redturtle/volto/overrides.zcml diff --git a/src/redturtle/volto/overrides.py b/src/redturtle/volto/overrides.py new file mode 100644 index 0000000..8932782 --- /dev/null +++ b/src/redturtle/volto/overrides.py @@ -0,0 +1,99 @@ +from Acquisition import aq_base +from plone.app.contenttypes.interfaces import IFile +from plone.indexer.decorator import indexer +from plone.rfc822.interfaces import IPrimaryFieldInfo +from Products.CMFCore.utils import getToolByName +from Products.PortalTransforms.libtransforms.utils import MissingBinary +from ZODB.POSException import ConflictError + +from plone.app.contenttypes.indexers import SearchableText, _unicode_save_string_concat +from redturtle.volto import logger +from hashlib import sha256 +from time import time + +_marker = object() + + +# see. Products/PortalTransforms/cache.py +class Cache: + def __init__(self, context, value, _id="_v_transform_cache"): + self.hash = sha256(value).hexdigest() + self.context = context + self._id = _id + + def setCache(self, key, value): + """cache a value indexed by key""" + if not value.isCacheable(): + return + context = self.context + if getattr(aq_base(context), self._id, None) is None: + setattr(context, self._id, {}) + getattr(context, self._id)[key] = (time(), self.hash, value) + return key + + def getCache(self, key): + """try to get a cached value for key + return _marker if not present + else return value + """ + obj = self.context + dict = getattr(obj, self._id, None) + if dict is None: + return _marker + try: + _, hash, value = dict.get(key, None) + if hash != self.hash: + return _marker + return value + except TypeError: + return _marker + + +# plone.app.contenttypes-3.0.5-py3.11.egg/plone/app/contenttypes/indexers.py +@indexer(IFile) +def SearchableText_file(obj): + try: + primary_field = IPrimaryFieldInfo(obj) + except TypeError: + logger.warn( + "Lookup of PrimaryField failed for {} " + "If renaming or importing please reindex!".format(obj.absolute_url()) + ) + return + if primary_field.value is None: + return SearchableText(obj) + mimetype = primary_field.value.contentType + transforms = getToolByName(obj, "portal_transforms") + if transforms._findPath(mimetype, "text/plain") is None: + # check if there is a valid transform available first + return SearchableText(obj) + value = primary_field.value.data + filename = primary_field.value.filename + try: + # CHANGES FROM HERE ... + cache = Cache(obj, value) + transformed_value = cache.getCache(key=(primary_field.fieldname, mimetype)) + if transformed_value is _marker: + logger.info("MISSING CACHE: %s", obj.absolute_url()) + transformed_value = transforms.convertTo( + "text/plain", value, mimetype=mimetype, filename=filename + ) + cache.setCache((primary_field.fieldname, mimetype), transformed_value) + else: + logger.info("HIT CACHE: %s", obj.absolute_url()) + # ... TO HERE. + if not transformed_value: + return SearchableText(obj) + return _unicode_save_string_concat( + SearchableText(obj), transformed_value.getData() + ) + except MissingBinary: + return SearchableText(obj) + except (ConflictError, KeyboardInterrupt): + raise + except Exception as msg: + logger.exception( + 'exception while trying to convert blob contents to "text/plain" ' + "for {}. Error: {}".format(obj, str(msg)), + ) + return SearchableText(obj) \ No newline at end of file diff --git a/src/redturtle/volto/overrides.zcml b/src/redturtle/volto/overrides.zcml new file mode 100644 index 0000000..19b1564 --- /dev/null +++ b/src/redturtle/volto/overrides.zcml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file From f6c9064c41998ab9df78fed6fb77f05cc6c3b273 Mon Sep 17 00:00:00 2001 From: Mauro Amico Date: Tue, 7 Nov 2023 18:33:02 +0100 Subject: [PATCH 2/2] black --- src/redturtle/volto/overrides.py | 2 +- src/redturtle/volto/overrides.zcml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/redturtle/volto/overrides.py b/src/redturtle/volto/overrides.py index 8932782..4401f0d 100644 --- a/src/redturtle/volto/overrides.py +++ b/src/redturtle/volto/overrides.py @@ -96,4 +96,4 @@ def SearchableText_file(obj): 'exception while trying to convert blob contents to "text/plain" ' "for {}. Error: {}".format(obj, str(msg)), ) - return SearchableText(obj) \ No newline at end of file + return SearchableText(obj) diff --git a/src/redturtle/volto/overrides.zcml b/src/redturtle/volto/overrides.zcml index 19b1564..9815611 100644 --- a/src/redturtle/volto/overrides.zcml +++ b/src/redturtle/volto/overrides.zcml @@ -11,4 +11,4 @@ name="SearchableText" /> - \ No newline at end of file +