From 7b651a5e5108656ccc09bc2334039e6bcbfac040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 6 Feb 2024 12:59:00 +0100 Subject: [PATCH] Lock table at transaction start for with_transaction decorator Since c8771e45b861 TransactionError is raised if a table is not locked at the transaction start. The decorator must manage such exception in case the decorated route needs to lock a table. Closes #12962 (grafted from bced72f6282bbb1ec2c58e7af25ca1e5a941b82f) --HG-- branch : 7.0 --- trytond/trytond/protocols/wrappers.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/trytond/trytond/protocols/wrappers.py b/trytond/trytond/protocols/wrappers.py index 63edb32326..5575654176 100644 --- a/trytond/trytond/protocols/wrappers.py +++ b/trytond/trytond/protocols/wrappers.py @@ -24,7 +24,7 @@ from trytond.config import config from trytond.exceptions import RateLimitException, UserError, UserWarning from trytond.pool import Pool from trytond.tools import cached_property -from trytond.transaction import Transaction, check_access +from trytond.transaction import Transaction, TransactionError, check_access __all__ = [ 'HTTPStatus', @@ -235,17 +235,24 @@ def with_transaction(readonly=None, user=0, context=None): else: user_ = user retry = config.getint('database', 'retry') - for count in range(retry, -1, -1): - if count != retry: + count = 0 + transaction_extras = {} + while True: + if count: time.sleep(0.02 * (retry - count)) with Transaction().start( pool.database_name, user_, readonly=readonly_, - context=context_) as transaction: + context=context_, **transaction_extras) as transaction: try: result = func(request, pool, *args, **kwargs) + except TransactionError as e: + transaction.rollback() + e.fix(transaction_extras) + continue except backend.DatabaseOperationalError: - if count and not readonly_: + if count < retry and not readonly_: transaction.rollback() + count += 1 continue raise # Need to commit to unlock SQLite database