Prevent Cache to start too much new transactions
resets starts a transaction only if there is something to store. clean is run at best every 5 minutes by default. issue7533 review64261002
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
* Add cache clean timeout configuration
|
||||
* Implicit conversion to boolean in PYSON statement
|
||||
* Add domain to dictionary schema
|
||||
* Fill main language in ir.configuration at database initialization
|
||||
|
||||
@@ -172,6 +172,13 @@ The number of field to load with an `eager` :attr:`Field.loading`.
|
||||
|
||||
Default: `100`
|
||||
|
||||
clean_timeout
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
The minimum number of seconds between two cleanings of the cache.
|
||||
|
||||
Default: `300`
|
||||
|
||||
table
|
||||
-----
|
||||
|
||||
|
||||
+23
-14
@@ -2,6 +2,7 @@
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from threading import Lock
|
||||
from collections import OrderedDict
|
||||
from datetime import datetime
|
||||
|
||||
from sql import Table
|
||||
from sql.functions import CurrentTimestamp
|
||||
@@ -11,6 +12,7 @@ from trytond.transaction import Transaction
|
||||
from trytond.tools import resolve
|
||||
|
||||
__all__ = ['BaseCache', 'Cache', 'LRUDict']
|
||||
_clear_timeout = config.getint('cache', 'clean_timeout', default=5 * 60)
|
||||
|
||||
|
||||
def freeze(o):
|
||||
@@ -68,6 +70,7 @@ class MemoryCache(BaseCache):
|
||||
"""
|
||||
_resets = {}
|
||||
_resets_lock = Lock()
|
||||
_clean_last = datetime.now()
|
||||
|
||||
def __init__(self, name, size_limit=1024, context=True):
|
||||
super(MemoryCache, self).__init__(name, size_limit, context)
|
||||
@@ -103,8 +106,10 @@ class MemoryCache(BaseCache):
|
||||
with self._lock:
|
||||
self._cache[dbname] = LRUDict(self.size_limit)
|
||||
|
||||
@staticmethod
|
||||
def clean(dbname):
|
||||
@classmethod
|
||||
def clean(cls, dbname):
|
||||
if (datetime.now() - cls._clean_last).total_seconds() < _clear_timeout:
|
||||
return
|
||||
with Transaction().new_transaction(_nocache=True) as transaction,\
|
||||
transaction.connection.cursor() as cursor:
|
||||
table = Table('ir_cache')
|
||||
@@ -112,28 +117,31 @@ class MemoryCache(BaseCache):
|
||||
timestamps = {}
|
||||
for timestamp, name in cursor.fetchall():
|
||||
timestamps[name] = timestamp
|
||||
for inst in Cache._cache_instance:
|
||||
for inst in cls._cache_instance:
|
||||
if inst._name in timestamps:
|
||||
with inst._lock:
|
||||
if (not inst._timestamp
|
||||
or timestamps[inst._name] > inst._timestamp):
|
||||
inst._timestamp = timestamps[inst._name]
|
||||
inst._cache[dbname] = LRUDict(inst.size_limit)
|
||||
cls._clean_last = datetime.now()
|
||||
|
||||
@staticmethod
|
||||
def reset(dbname, name):
|
||||
with Cache._resets_lock:
|
||||
Cache._resets.setdefault(dbname, set())
|
||||
Cache._resets[dbname].add(name)
|
||||
@classmethod
|
||||
def reset(cls, dbname, name):
|
||||
with cls._resets_lock:
|
||||
cls._resets.setdefault(dbname, set())
|
||||
cls._resets[dbname].add(name)
|
||||
|
||||
@staticmethod
|
||||
def resets(dbname):
|
||||
@classmethod
|
||||
def resets(cls, dbname):
|
||||
table = Table('ir_cache')
|
||||
resets = cls._resets.setdefault(dbname, set())
|
||||
if not resets:
|
||||
return
|
||||
with Transaction().new_transaction(_nocache=True) as transaction,\
|
||||
transaction.connection.cursor() as cursor,\
|
||||
Cache._resets_lock:
|
||||
Cache._resets.setdefault(dbname, set())
|
||||
for name in Cache._resets[dbname]:
|
||||
cls._resets_lock:
|
||||
for name in resets:
|
||||
cursor.execute(*table.select(table.name,
|
||||
where=table.name == name,
|
||||
limit=1))
|
||||
@@ -146,13 +154,14 @@ class MemoryCache(BaseCache):
|
||||
cursor.execute(*table.insert(
|
||||
[table.timestamp, table.name],
|
||||
[[CurrentTimestamp(), name]]))
|
||||
Cache._resets[dbname].clear()
|
||||
resets.clear()
|
||||
|
||||
@classmethod
|
||||
def drop(cls, dbname):
|
||||
for inst in cls._cache_instance:
|
||||
inst._cache.pop(dbname, None)
|
||||
|
||||
|
||||
if config.get('cache', 'class'):
|
||||
Cache = resolve(config.get('cache', 'class'))
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user