remove caching

This commit is contained in:
Frederik Jaeckel 2023-12-23 10:36:58 +01:00
parent c6478add0f
commit 345cef4c8b
5 changed files with 10 additions and 258 deletions

View file

@ -16,12 +16,10 @@ from .category import Category
from .reconciliation import Reconciliation
from .cbreport import ReconciliationReport
from .currency import CurrencyRate
from .model import MemCache
def register():
Pool.register(
MemCache,
Configuration,
UserConfiguration,
CurrencyRate,

41
book.py
View file

@ -12,22 +12,12 @@ from trytond.i18n import gettext
from trytond.transaction import Transaction
from trytond.pool import Pool
from trytond.report import Report
from trytond.config import config
from decimal import Decimal
from datetime import date
from sql.aggregate import Sum
from sql.conditionals import Case
from .model import order_name_hierarchical, sub_ids_hierarchical, \
AnyInArray, CACHEKEY_CURRENCY
# enable/disable caching of cachekey for 'currency.rate'
if config.get(
'cashbook', 'cache_currency', default='yes'
).lower() in ['yes', '1', 'true']:
ENA_CURRKEY = True
else:
ENA_CURRKEY = False
from .model import (
order_name_hierarchical, sub_ids_hierarchical, AnyInArray)
STATES = {
@ -402,7 +392,6 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView):
Currency = pool.get('currency.currency')
Company = pool.get('company.company')
IrDate = pool.get('ir.date')
MemCache = pool.get('cashbook.memcache')
tab_book = Book2.__table__()
tab_comp = Company.__table__()
cursor = Transaction().connection.cursor()
@ -420,28 +409,6 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView):
except Exception:
query_date = IrDate.today()
cache_keys = {
x.id: MemCache.get_key_by_record(
name='get_balance_cashbook',
record=x,
query=[{
'model': 'cashbook.line',
'query': [('cashbook.parent', 'child_of', [x.id])],
}, {
'model': 'currency.currency.rate',
'query': [('currency.id', '=', x.currency.id)],
'cachekey' if ENA_CURRKEY
else 'disabled': CACHEKEY_CURRENCY % x.currency.id,
}, ],
addkeys=[query_date.isoformat()])
for x in cashbooks}
# read from cache
(todo_cashbook, result) = MemCache.read_from_cache(
cashbooks, cache_keys, names, result)
if len(todo_cashbook) == 0:
return result
# query balances of cashbooks and sub-cashbooks
with Transaction().set_context({
'date': query_date}):
@ -466,7 +433,7 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView):
Sum(tab_line.balance_all).as_('balance_all'),
group_by=[
tab_book.id, tab_line.currency, tab_comp.currency],
where=tab_book.id.in_([x.id for x in todo_cashbook]),
where=tab_book.id.in_([x.id for x in cashbooks]),
)
cursor.execute(*query)
records = cursor.fetchall()
@ -478,8 +445,6 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView):
record[2], record[5], record[1])
result['balance_ref'][record[0]] += Currency.compute(
record[2], record[5], record[3])
MemCache.store_result(cashbooks, cache_keys, result, todo_cashbook)
return result
@fields.depends('btype')

View file

@ -3,8 +3,7 @@
# The COPYRIGHT file at the top level of this repository contains the
# full copyright notices and license terms.
from trytond.pool import Pool, PoolMeta
from .model import CACHEKEY_CURRENCY
from trytond.pool import PoolMeta
class CurrencyRate(metaclass=PoolMeta):
@ -14,36 +13,22 @@ class CurrencyRate(metaclass=PoolMeta):
def create(cls, vlist):
""" update cache-value
"""
MemCache = Pool().get('cashbook.memcache')
records = super(CurrencyRate, cls).create(vlist)
for rate in records:
MemCache.record_update(CACHEKEY_CURRENCY % rate.currency.id, rate)
# TODO: update cashbooks using this rate
return records
@classmethod
def write(cls, *args):
""" update cache-value
"""
MemCache = Pool().get('cashbook.memcache')
super(CurrencyRate, cls).write(*args)
actions = iter(args)
for rates, values in zip(actions, actions):
for rate in rates:
MemCache.record_update(
CACHEKEY_CURRENCY % rate.currency.id, rate)
# TODO: update cashbooks using this rate
@classmethod
def delete(cls, records):
""" set cache to None
"""
MemCache = Pool().get('cashbook.memcache')
for record in records:
MemCache.record_update(
CACHEKEY_CURRENCY % record.currency.id, None)
super(CurrencyRate, cls).delete(records)
# TODO: update cashbooks using this rate
# end

172
model.py
View file

@ -4,35 +4,14 @@
# full copyright notices and license terms.
from trytond.model import (
MultiValueMixin, ValueMixin, fields, Unique, Model, Index)
MultiValueMixin, ValueMixin, fields, Unique, Index)
from trytond.transaction import Transaction
from trytond.pool import Pool
from trytond.cache import MemoryCache
from trytond.config import config
from datetime import timedelta
from decimal import Decimal
from sql import With
from sql.functions import Function
from sql.conditionals import Coalesce
import copy
from .const import DEF_NONE
if config.get('cashbook', 'memcache', default='yes').lower() \
in ['yes', '1', 'true']:
ENABLE_CACHE = True
else:
ENABLE_CACHE = False
if config.get('cashbook', 'sync', default='yes').lower() \
in ['yes', '1', 'true']:
ENABLE_CACHESYNC = True
else:
ENABLE_CACHESYNC = False
CACHEKEY_CURRENCY = 'currency-%s'
class ArrayAgg(Function):
"""input values, including nulls, concatenated into an array.
"""
@ -86,155 +65,6 @@ class Array(Function):
# end Array
class MemCache(Model):
""" store values to cache
"""
__name__ = 'cashbook.memcache'
_cashbook_value_cache = MemoryCache(
'cashbook.book.valuecache',
context=False,
duration=timedelta(seconds=60*60*4))
@classmethod
def read_value(cls, cache_key):
""" read values from cache
"""
if ENABLE_CACHE is False:
return None
return copy.deepcopy(cls._cashbook_value_cache.get(cache_key))
@classmethod
def store_result(cls, records, cache_keys, values, skip_records=[]):
""" store result to cache
"""
if ENABLE_CACHE is False:
return
for record in records:
if record not in skip_records:
continue
data = {
x: values[x][record.id]
for x in values.keys() if record.id in values[x].keys()}
cls._cashbook_value_cache.set(
cache_keys[record.id], copy.deepcopy(data))
if ENABLE_CACHESYNC is True:
cls._cashbook_value_cache.sync(Transaction())
@classmethod
def store_value(cls, cache_key, values):
""" store values to cache
"""
if ENABLE_CACHE is False:
return
cls._cashbook_value_cache.set(cache_key, copy.deepcopy(values))
@classmethod
def read_from_cache(cls, records, cache_keys, names, result):
""" get stored values from memcache
"""
if ENABLE_CACHE is False:
return (records, result)
todo_records = []
for record in records:
values = copy.deepcopy(cls.read_value(cache_keys[record.id]))
if values:
for name in names:
if name not in values.keys():
continue
if values[name] is None:
continue
if result[name][record.id] is None:
result[name][record.id] = Decimal('0.0')
result[name][record.id] += values[name]
else:
todo_records.append(record)
return (todo_records, result)
@classmethod
def get_key_by_record(cls, name, record, query, addkeys=[]):
""" read records to build a cache-key
"""
pool = Pool()
cursor = Transaction().connection.cursor()
if ENABLE_CACHE is False:
return '-'
fname = [name, str(record.id)]
fname.extend(addkeys)
# query the last edited record for each item in 'query'
for line in query:
if len(line.keys()) == 0:
continue
if 'cachekey' in line.keys():
key = cls.read_value(line['cachekey'])
if key:
fname.append(key)
continue
Model = pool.get(line['model'])
tab_model = Model.__table__()
tab_query = Model.search(line['query'], query=True)
qu1 = tab_model.join(
tab_query,
condition=tab_query.id == tab_model.id,
).select(
tab_model.id,
tab_model.write_date,
tab_model.create_date,
limit=1,
order_by=[
Coalesce(
tab_model.write_date, tab_model.create_date).desc,
tab_model.id.desc,
],
)
cursor.execute(*qu1)
records = cursor.fetchall()
if len(records) > 0:
fname.append(cls.genkey(
records[0][0],
records[0][1],
records[0][2],
))
else:
fname.append('0')
if 'cachekey' in line.keys():
key = cls.store_value(line['cachekey'], fname[-1])
return '-'.join(fname)
@classmethod
def genkey(cls, id_record, write_date, create_date):
""" get key as text
"""
date_val = write_date if write_date is not None else create_date
return '-'.join([
str(id_record),
'%s%s' % (
'w' if write_date is not None else 'c',
date_val.timestamp() if date_val is not None else '-'),
])
@classmethod
def record_update(cls, cache_key, record):
""" update cache-value
"""
if ENABLE_CACHE is False:
return
cls.store_value(
cache_key,
cls.genkey(record.id, record.write_date, record.create_date)
if record is not None else None)
# end mem_cache
def sub_ids_hierarchical(model_name):
""" get table with id and sub-ids
"""

View file

@ -5,10 +5,8 @@
from trytond.tests.test_tryton import with_transaction
from trytond.pool import Pool
from trytond.modules.cashbook.model import CACHEKEY_CURRENCY, ENABLE_CACHE
from datetime import date
from decimal import Decimal
import time
class CurrencyTestCase(object):
@ -19,20 +17,15 @@ class CurrencyTestCase(object):
""" add/update/del rate of currency, check cache
"""
pool = Pool()
MemCache = pool.get('cashbook.memcache')
Currency = pool.get('currency.currency')
CurrencyRate = pool.get('currency.currency.rate')
self.prep_config()
self.prep_company()
MemCache._cashbook_value_cache.clear_all()
# TODO: check update of cashbook if currency changes
currency, = Currency.search([('name', '=', 'usd')])
cache_key = CACHEKEY_CURRENCY % currency.id
# cache should be empty
self.assertEqual(MemCache.read_value(cache_key), None)
CurrencyRate.delete(currency.rates)
self.assertEqual(len(currency.rates), 0)
@ -47,16 +40,6 @@ class CurrencyTestCase(object):
}])
self.assertEqual(len(currency.rates), 1)
# expected key
value = '%d-c%s' % (
currency.rates[0].id,
str(currency.rates[0].create_date.timestamp()))
if ENABLE_CACHE is True:
self.assertEqual(MemCache.read_value(cache_key), value)
else:
self.assertEqual(MemCache.read_value(cache_key), None)
time.sleep(1.0)
Currency.write(*[
[currency],
{
@ -67,19 +50,10 @@ class CurrencyTestCase(object):
}])
self.assertEqual(len(currency.rates), 1)
value = '%d-w%s' % (
currency.rates[0].id,
str(currency.rates[0].write_date.timestamp()))
if ENABLE_CACHE is True:
self.assertEqual(MemCache.read_value(cache_key), value)
else:
self.assertEqual(MemCache.read_value(cache_key), None)
Currency.write(*[
[currency],
{
'rates': [('delete', [currency.rates[0].id])],
}])
self.assertEqual(MemCache.read_value(cache_key), None)
# end CurrencyTestCase