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':

Reply via email to