[FIX] models: manage environment when loading records
When testing the import of records, a flush should be done to check all databases constraints and fields computations. Moreover, in case an exception is raised within a savepoint, the environment should be cleaned up, to avoid tricky bugs (see below). We replace the manual handling of savepoints with the savepoint context manager, which already handles all of this. This code predates the context manager, so in a way it was archaic. When testing the import of records, the following could happen: "An unknown issue occurred during import (possibly lost connection, data limit exceeded or memory limits exceeded)." This would happen on project tasks; the fields 'working_hours_open', 'working_hours_close', 'working_days_open', 'working_days_close', all depend on the computation of _compute_elapsed. Because this is a test import, the records would raise a MissingError, and fields_to_compute would always contain 3 of the fields. The resulting is an infinite loop giving this error. opw 2092134 closes odoo/odoo#39682 X-original-commit: 1a315e87b05fcbdefcb3db6d8d4837f6cc3e835c Signed-off-by: Nans Lefebvre (len) <len@odoo.com> Co-authored-by: Raphael Collet <rco@odoo.com>
This commit is contained in:
committed by
fw-bot
co-authored by
Raphael Collet
parent
6901adbe98
commit
f2a1618758
+9
-11
@@ -859,6 +859,8 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
|
||||
:type data: list(list(str))
|
||||
:returns: {ids: list(int)|False, messages: [Message][, lastrow: int]}
|
||||
"""
|
||||
self.flush()
|
||||
|
||||
# determine values of mode, current_module and noupdate
|
||||
mode = self._context.get('mode', 'init')
|
||||
current_module = self._context.get('module', '__import__')
|
||||
@@ -905,30 +907,27 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
|
||||
|
||||
# try to create in batch
|
||||
try:
|
||||
recs = self._load_records(data_list, mode == 'update')
|
||||
ids.extend(recs.ids)
|
||||
cr.execute('RELEASE SAVEPOINT model_load_save')
|
||||
with cr.savepoint():
|
||||
recs = self._load_records(data_list, mode == 'update')
|
||||
ids.extend(recs.ids)
|
||||
return
|
||||
except Exception:
|
||||
cr.execute('ROLLBACK TO SAVEPOINT model_load_save')
|
||||
pass
|
||||
|
||||
# try again, this time record by record
|
||||
for rec_data in data_list:
|
||||
try:
|
||||
cr.execute('SAVEPOINT model_load_save')
|
||||
rec = self._load_records([rec_data], mode == 'update')
|
||||
ids.append(rec.id)
|
||||
cr.execute('RELEASE SAVEPOINT model_load_save')
|
||||
with cr.savepoint():
|
||||
rec = self._load_records([rec_data], mode == 'update')
|
||||
ids.append(rec.id)
|
||||
except psycopg2.Warning as e:
|
||||
info = rec_data['info']
|
||||
messages.append(dict(info, type='warning', message=str(e)))
|
||||
cr.execute('ROLLBACK TO SAVEPOINT model_load_save')
|
||||
except psycopg2.Error as e:
|
||||
info = rec_data['info']
|
||||
messages.append(dict(info, type='error', **PGERROR_TO_OE[e.pgcode](self, fg, info, e)))
|
||||
# Failed to write, log to messages, rollback savepoint (to
|
||||
# avoid broken transaction) and keep going
|
||||
cr.execute('ROLLBACK TO SAVEPOINT model_load_save')
|
||||
except Exception as e:
|
||||
_logger.exception("Error while loading record")
|
||||
info = rec_data['info']
|
||||
@@ -937,7 +936,6 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
|
||||
messages.append(dict(info, type='error', message=message, moreinfo=moreinfo))
|
||||
# Failed for some reason, perhaps due to invalid data supplied,
|
||||
# rollback savepoint and keep going
|
||||
cr.execute('ROLLBACK TO SAVEPOINT model_load_save')
|
||||
|
||||
# make 'flush' available to the methods below, in the case where XMLID
|
||||
# resolution fails, for instance
|
||||
|
||||
Reference in New Issue
Block a user