[FIX] hr_work_entry: stop shadowing concurrent updates

The `_error_checking()` context manager is used to perform validation
and cleanup after changes on work entries, and is implemented using a
try/finally clause.

This mechanism fails to take into account that the alteration operation
can fail due to a concurrent update (in another transaction). In such a
situation the db cursor becomes instantly invalid, and any attempt to
use it will fail with:
  `psycopg2.InternalError: current transaction is aborted`.
This exception will be raised in the `finally` block, and will therefore
discard the original TransactionRollbackException.

The result: instead of being silently retried as expected,
the transaction fails and the user receives a cryptic error message.

Steps to repro: repeatedly click on the button to validate a leave

Solution: specifically handle PostgreSQL `OperationalError` exceptions
and do not attempt to use the cursor when they occur - just let the
exception bubble up.

closes odoo/odoo#59612

X-original-commit: 7ba47e7215df69b6556a848532e4f33ef4243e83
Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
This commit is contained in:
Olivier Dony
2020-10-09 11:18:21 +00:00
parent a8dad56d6b
commit cfa20f3eff
@@ -3,6 +3,7 @@
from contextlib import contextmanager
from dateutil.relativedelta import relativedelta
from psycopg2 import OperationalError
from odoo import api, fields, models
@@ -169,6 +170,11 @@ class HrWorkEntry(models.Model):
])
work_entries._reset_conflicting_state()
yield
except OperationalError:
# the cursor is dead, do not attempt to use it or we will shadow the root exception
# with a "psycopg2.InternalError: current transaction is aborted, ..."
skip = True
raise
finally:
if not skip and start and stop:
# New work entries are handled in the create method,