[FIX] base: allow get_template serialization retry

When two transactions conflicts (eg. deleting same data, see [1]) Odoo
will retry the whole transaction several times hoping for the best.

But when rendering template, the error handling would prevent this
feature. For example a recurring issue was:

- loading quickly two times the /web route
- for each recompute the assets

=> this could lead to 2 concurrents transactions that would delete
previous same attachment (ie. DELETE FROM ir_attachment where id=3).

With this changeset, when getting a template fails because of a
transaction rollback, we let the issue bubble up so our retry system is
used.

So instead of a "500 Internal Server Error" page and in log:

  bad query: b'DELETE FROM ir_attachment WHERE id IN (3)'
  ERROR: could not serialize access due to concurrent update
  "GET /web HTTP/1.1" 200 -
  "GET /web HTTP/1.1" 500 -
  ... big traceback ...
  load could not load template

we would get the requested page without error and:

  bad query: b'DELETE FROM ir_attachment WHERE id IN (3)'
  ERROR: could not serialize access due to concurrent update
  "GET /web HTTP/1.1" 200 -
  SERIALIZATION_FAILURE, retry 1/5 in 0.8920 sec..
  "GET /web HTTP/1.1" 200 -

As a side node, the issue was exacerbated in some instances:

- when running a database on another server: assets are recomputed
- when a module was installed/uninstalled: assets may are recomputed
- when updating the source code: assets may be recomputed
- when starting server: requests could be stacked waiting for readiness
- when using google chrome: the "Use a prediction service to load pages
  more quickly" option may load a page two times. for example:
    -> an URL is entered in address bar
    -> a prediction request to it is started URL
    -> go to this page (Enter) when that request is not already resolved
    -> the prediction request is cancelled and a new request is started

[1] https://www.postgresql.org/docs/9.6/static/transaction-iso.html#XACT-REPEATABLE-READ

note: 10.0 backport of 11.0 #26778

opw-1849167
closes #26785
This commit is contained in:
Nicolas Lempereur
2018-09-05 10:20:50 +02:00
parent e673484b35
commit 1d0940d96f
+2 -1
View File
@@ -5,6 +5,7 @@ from lxml import etree, html
import re
import traceback
from itertools import count
from psycopg2.extensions import TransactionRollbackError
from textwrap import dedent
import werkzeug
from werkzeug.utils import escape as _escape
@@ -313,7 +314,7 @@ class QWeb(object):
values = dict(self.default_values(), **values)
try:
return compiled(self, append, values, options, log)
except QWebException, e:
except (QWebException, TransactionRollbackError) as e:
raise e
except Exception, e:
path = log['last_path_node']