diff --git a/addons/bus/models/bus_presence.py b/addons/bus/models/bus_presence.py index c1da707b215..d25ef09314a 100644 --- a/addons/bus/models/bus_presence.py +++ b/addons/bus/models/bus_presence.py @@ -2,9 +2,12 @@ import datetime import time +from psycopg2 import OperationalError + from odoo import api, fields, models from odoo import tools from odoo.addons.bus.models.bus import TIMEOUT +from odoo.service.model import PG_CONCURRENCY_ERRORS_TO_RETRY from odoo.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT DISCONNECTION_TIMER = TIMEOUT + 5 @@ -34,6 +37,23 @@ class BusPresence(models.Model): """ Updates the last_poll and last_presence of the current user :param inactivity_period: duration in milliseconds """ + # This method is called in method _poll() and cursor is closed right + # after; see bus/controllers/main.py. + try: + # Hide transaction serialization errors, which can be ignored, the presence update is not essential + # The errors are supposed from presence.write(...) call only + with tools.mute_logger('odoo.sql_db'): + self._update(inactivity_period) + # commit on success + self.env.cr.commit() + except OperationalError as e: + if e.pgcode in PG_CONCURRENCY_ERRORS_TO_RETRY: + # ignore concurrency error + return self.env.cr.rollback() + raise + + @api.model + def _update(self, inactivity_period): presence = self.search([('user_id', '=', self._uid)], limit=1) # compute last_presence timestamp last_presence = datetime.datetime.now() - datetime.timedelta(milliseconds=inactivity_period) @@ -48,8 +68,4 @@ class BusPresence(models.Model): else: # update the last_presence if necessary, and write values if presence.last_presence < last_presence: values['last_presence'] = last_presence - # Hide transaction serialization errors, which can be ignored, the presence update is not essential - with tools.mute_logger('odoo.sql_db'): - presence.write(values) - # avoid TransactionRollbackError - self.env.cr.commit() # TODO : check if still necessary + presence.write(values)