changeset f816cd0d481f in trytond:default details: https://hg.tryton.org/trytond?cmd=changeset;node=f816cd0d481f description: Do use translation cache if records were modified after last synchronisation
On distributed setup, the cache is not synchronized instantaneously so we can not use the cache if the record was modified by another process since the last synchronisation. issue9013 review262841002 diffstat: doc/ref/cache.rst | 4 ++++ trytond/cache.py | 8 ++++++++ trytond/ir/translation.py | 13 ++++++++----- trytond/model/modelsql.py | 8 +++++++- 4 files changed, 27 insertions(+), 6 deletions(-) diffs (133 lines): diff -r 252ef79e6896 -r f816cd0d481f doc/ref/cache.rst --- a/doc/ref/cache.rst Thu Feb 13 18:02:05 2020 +0100 +++ b/doc/ref/cache.rst Sat Feb 15 01:36:48 2020 +0100 @@ -39,6 +39,10 @@ Synchronize cache instances using transaction. +.. method:: sync_since(value) + +Return `True` if the last synchronization was done before `value`. + .. classmethod:: commit(transaction) Apply cache changes from transaction. diff -r 252ef79e6896 -r f816cd0d481f trytond/cache.py --- a/trytond/cache.py Thu Feb 13 18:02:05 2020 +0100 +++ b/trytond/cache.py Sat Feb 15 01:36:48 2020 +0100 @@ -78,6 +78,9 @@ def sync(cls, transaction): raise NotImplementedError + def sync_since(self, value): + raise NotImplementedError + @classmethod def commit(cls, transaction): raise NotImplementedError @@ -197,6 +200,9 @@ inst._clear(dbname, timestamp) cls._clean_last = datetime.now() + def sync_since(self, value): + return self._clean_last > value + @classmethod def commit(cls, transaction): table = Table(cls._table) @@ -245,6 +251,7 @@ connection.commit() finally: database.put_connection(connection) + cls._clean_last = datetime.now() reset.clear() @classmethod @@ -299,6 +306,7 @@ for name in reset: inst = cls._instances[name] inst._clear(dbname) + cls._clean_last = datetime.now() except Exception: logger.error( "cache listener on '%s' crashed", dbname, exc_info=True) diff -r 252ef79e6896 -r f816cd0d481f trytond/ir/translation.py --- a/trytond/ir/translation.py Thu Feb 13 18:02:05 2020 +0100 +++ b/trytond/ir/translation.py Sat Feb 15 01:36:48 2020 +0100 @@ -285,11 +285,13 @@ return [('/form//field[@name="value"]', 'spell', Eval('lang'))] @classmethod - def get_ids(cls, name, ttype, lang, ids): + def get_ids(cls, name, ttype, lang, ids, cached_after=None): "Return translation for each id" pool = Pool() ModelFields = pool.get('ir.model.field') Model = pool.get('ir.model') + context = Transaction().context + fuzzy_translation = context.get('fuzzy_translation', False) translations, to_fetch = {}, [] name = str(name) @@ -326,8 +328,9 @@ return translations # Don't use cache for fuzzy translation - if not Transaction().context.get( - 'fuzzy_translation', False): + if (not fuzzy_translation + and (not cached_after + or not cls._translation_cache.sync_since(cached_after))): for obj_id in ids: trans = cls._translation_cache.get((name, ttype, lang, obj_id), -1) @@ -345,7 +348,7 @@ translations.update( cls.get_ids(name, ttype, parent_lang, to_fetch)) - if Transaction().context.get('fuzzy_translation', False): + if fuzzy_translation: fuzzy_clause = [] else: fuzzy_clause = [('fuzzy', '=', False)] @@ -360,7 +363,7 @@ ] + fuzzy_clause): translations[translation.res_id] = translation.value # Don't store fuzzy translation in cache - if not Transaction().context.get('fuzzy_translation', False): + if not fuzzy_translation: for res_id in to_fetch: value = translations.setdefault(res_id) cls._translation_cache.set( diff -r 252ef79e6896 -r f816cd0d481f trytond/model/modelsql.py --- a/trytond/model/modelsql.py Thu Feb 13 18:02:05 2020 +0100 +++ b/trytond/model/modelsql.py Sat Feb 15 01:36:48 2020 +0100 @@ -692,6 +692,8 @@ fields_related = defaultdict(set) extra_fields = set() + if 'write_date' not in fields_names: + extra_fields.add('write_date') for field_name in fields_names: if field_name == '_timestamp': continue @@ -765,6 +767,9 @@ result = [{'id': x} for x in ids] cachable_fields = [] + max_write_date = max( + (r['write_date'] for r in result if r.get('write_date')), + default=None) for column in columns: # Split the output name to remove SQLite type detection fname = column.output_name.split()[0] @@ -775,7 +780,8 @@ if getattr(field, 'translate', False): translations = Translation.get_ids( cls.__name__ + ',' + fname, 'model', - Transaction().language, ids) + Transaction().language, ids, + cached_after=max_write_date) for row in result: row[fname] = translations.get(row['id']) or row[fname] if fname != 'id':