キャッシュの大きさやデータ飽和などで問題を引き起こすと考えられる場合は、独自のキャッシュを使用したいと思います。
以下の上級者向けの例では、HTML 変換した結果をカスタム RAM キャッシュに保存することにより、既存のコンテントタイプの本文と説明にアクセスするメソッドを強化する方法を説明します。
例:
import logging
import lxml.html
from zope.app.cache import ram
from Products.feedfeeder.content.item import FeedFeederItem
from gomobile.xhtmlmp.transformers.xhtmlmp_safe import clean_xhtml_mp
logger = logging.getLogger("GoMobile")
logger.info("Running in feedfeeder monkey-patches")
# Cache storing transformed XHTML
xhtml_cache = ram.RAMCache()
xhtml_cache.update(maxAge=86400, maxEntries=1000)
# Dummy object to mark missing values from cache
_marker = object()
def cache(name):
""" Special cache decorator which generates cache key based on context object and cache name """
def decorator(fun):
def replacement(context):
key = str(context.UID()) + "." + name
cached_value = xhtml_cache.query(key, default=_marker)
if cached_value is _marker:
cached_value = fun(context)
xhtml_cache.set(cached_value, key)
return cached_value
return replacement
return decorator
def flush_cache(name, context):
""" Clear entry in RAMCache
global_key is function specific key, key is context specific key.
"""
key = context.UID() + "." + name
xhtml_cache.invalidate(key)
#
# Modify existing body text and description accessors so that
# 1) HTML is cleaned
# 2) The result cleaned HTML is cached in RAM
#
# We do not persistently want to store cleaned HTML,
# since our cleaner might be b0rked and we want to easily
# regenerate cleaned HTML when needed.
#
# Run in monkey patching
FeedFeederItem._old_getText = FeedFeederItem.getText
FeedFeederItem._old_setText = FeedFeederItem.setText
FeedFeederItem._old_Description = FeedFeederItem.Description
FeedFeederItem._old_setDescription = FeedFeederItem.setDescription
@cache("text")
def _getText(self):
""" Body text accessor """
text = FeedFeederItem._old_getText(self)
if text:
# can be None
clean = clean_xhtml_mp(text)
print "Cleaned text:" + clean
return clean
return text
def _setText(self, value):
FeedFeederItem._old_setText(self, value)
flush_cache("text", self)
@cache("description")
def _Description(self):
""" Description accessor """
text = FeedFeederItem._old_Description(self)
#print "Accessing description:" + str(text)
# Remove any HTML formatting in the description
if text:
parsed = lxml.html.fromstring(text.decode("utf-8"))
clean = lxml.html.tostring(parsed, encoding="utf-8", method="text").decode("utf-8")
#print "Cleaned decsription:" + clean
return clean
return text
def _setDescription(self, value):
FeedFeederItem._old_setDescription(self, value)
flush_cache("description", self)
FeedFeederItem.getText = _getText
FeedFeederItem.setText = _setText
FeedFeederItem.Description = _Description
FeedFeederItem.setDescription = _setDescription