RAM キャッシュ

はじめに

RAM キャッシュはプロセス中のカスタム・キャッシュを作成する zope の機能です。

カスタム RAM キャッシュを使用する

キャッシュの大きさやデータ飽和などで問題を引き起こすと考えられる場合は、独自のキャッシュを使用したいと思います。

以下の上級者向けの例では、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

目次

前のトピックへ

キャッシュ・デコレーター

次のトピックへ

(パフォーマンスの tips)

このページ