diff --git a/CHANGELOG b/CHANGELOG index 12d2b2e5f8..6528d1abe6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Allow to override cache implementation * Add button rule * Allow to specify translatable languages in trytond-admin * Add datetime_field on Reference diff --git a/doc/ref/cache.rst b/doc/ref/cache.rst new file mode 100644 index 0000000000..e151d6862e --- /dev/null +++ b/doc/ref/cache.rst @@ -0,0 +1,50 @@ +.. _ref-cache: +.. module:: trytond.cache + +===== +Cache +===== + +.. class:: Cache(name[, size_limit[, context]]) + +The class is used to cache values between server requests. The `name` should +be unique and it's used to identify the cache. We usually use +`.` to make it unique. The `size_limit` field can +be used to limit the number of values cached and the `context` parameter +is used to indicate if the cache depends on the user context and is true +by default. + +.. method:: get(key[, default]) + +Retrieve the value of the key in the cache. If a `default` is specified it +will be returned when the key is missing otherwise it will return `None`. + +.. method:: set(key, value) + +Sets the `value` of the `key` in the cache. + +.. method:: clear() + +Clears all the keys in the cache. + +.. staticmethod:: clean(dbname) + +Clean the cache for database `dbname` + +.. staticmethod:: reset(dbname, name) + +Reset the `name` cache for database `dbname` + +.. staticmethod:: resets(dbname) + +Resets all the caches stored for database `dbname` + +.. staticmethod:: drop(dbname) + +Drops all the caches for database `dbname` + +.. note:: + By default Tryton uses a MemoryCache, but this behaviour can be overridden + by setting a fully qualified name of an alternative class defined in the + configuration `class` of the `cache` section. +.. diff --git a/doc/ref/index.rst b/doc/ref/index.rst index 1374bfb34f..eeeecc299a 100644 --- a/doc/ref/index.rst +++ b/doc/ref/index.rst @@ -16,3 +16,4 @@ API Reference rpc sendmail filestore + cache diff --git a/trytond/cache.py b/trytond/cache.py index 4a89382ee2..a7845480a8 100644 --- a/trytond/cache.py +++ b/trytond/cache.py @@ -6,9 +6,11 @@ from collections import OrderedDict from sql import Table from sql.functions import CurrentTimestamp +from trytond.config import config from trytond.transaction import Transaction +from trytond.tools import resolve -__all__ = ['Cache', 'LRUDict'] +__all__ = ['BaseCache', 'Cache', 'LRUDict'] def freeze(o): @@ -20,28 +22,59 @@ def freeze(o): return o -class Cache(object): - """ - A key value LRU cache with size limit. - """ +class BaseCache(object): _cache_instance = [] - _resets = {} - _resets_lock = Lock() def __init__(self, name, size_limit=1024, context=True): + self._name = name self.size_limit = size_limit self.context = context - self._cache = {} self._cache_instance.append(self) - self._name = name - self._timestamp = None - self._lock = Lock() def _key(self, key): if self.context: return (key, Transaction().user, freeze(Transaction().context)) return key + def get(self, key, default=None): + raise NotImplemented + + def set(self, key, value): + raise NotImplemented + + def clear(self): + raise NotImplemented + + @staticmethod + def clean(dbname): + raise NotImplemented + + @staticmethod + def reset(dbname, name): + raise NotImplemented + + @staticmethod + def resets(dbname): + raise NotImplemented + + @classmethod + def drop(cls, dbname): + raise NotImplemented + + +class MemoryCache(BaseCache): + """ + A key value LRU cache with size limit. + """ + _resets = {} + _resets_lock = Lock() + + def __init__(self, name, size_limit=1024, context=True): + super(MemoryCache, self).__init__(name, size_limit, context) + self._cache = {} + self._timestamp = None + self._lock = Lock() + def get(self, key, default=None): dbname = Transaction().database.name key = self._key(key) @@ -119,6 +152,11 @@ class Cache(object): for inst in cls._cache_instance: inst._cache.pop(dbname, None) +if config.get('cache', 'class'): + Cache = resolve(config.get('cache', 'class')) +else: + Cache = MemoryCache + class LRUDict(OrderedDict): """