From aa2133a86946b16b7d3be29ff262cb6d7b379937 Mon Sep 17 00:00:00 2001 From: tsm-odoo Date: Fri, 7 Jul 2023 12:04:53 +0000 Subject: [PATCH] [FIX] mail: bad serialization error catching on message post MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `/mail/message/post` route wrongly prevent serialization errors by suppressing any `OperationalError` when writing on a canned response. This is wrong since the `write` method does not issue any SQL. In order to properly prevent serialization errors, the request is now done with the `SKIP LOCKED` clause. This is better since the error does not occur, hence: - No rollback needed - No need to mute the sql logger - No need to suppress any exception closes odoo/odoo#127761 Signed-off-by: Sébastien Theys (seb) --- addons/mail/controllers/thread.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/addons/mail/controllers/thread.py b/addons/mail/controllers/thread.py index 601b468e3f1..1227a2c3de1 100644 --- a/addons/mail/controllers/thread.py +++ b/addons/mail/controllers/thread.py @@ -1,9 +1,7 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. -from contextlib import suppress from datetime import datetime from markupsafe import Markup -from psycopg2 import OperationalError from werkzeug.exceptions import NotFound from odoo import http @@ -67,11 +65,20 @@ class ThreadController(http.Controller): def mail_message_post(self, thread_model, thread_id, post_data, context=None): if context: request.update_context(**context) - if "canned_response_ids" in post_data: - canned_response_ids = request.env['mail.shortcode'].browse(post_data.pop('canned_response_ids')) - # Ignore concurrency errors when saving last used date - with suppress(OperationalError): - canned_response_ids.write({'last_used': datetime.now()}) + canned_response_ids = tuple(cid for cid in post_data.pop('canned_response_ids', []) if isinstance(cid, int)) + if canned_response_ids: + # Avoid serialization errors since last used update is not + # essential and should not block message post. + request.env.cr.execute(""" + UPDATE mail_shortcode SET last_used=%(last_used)s + WHERE id IN ( + SELECT id from mail_shortcode WHERE id IN %(ids)s + FOR NO KEY UPDATE SKIP LOCKED + ) + """, { + 'last_used': datetime.now(), + 'ids': canned_response_ids, + }) thread = request.env[thread_model]._get_from_request_or_raise(request, int(thread_id)) if "body" in post_data: post_data["body"] = Markup(post_data["body"]) # contains HTML such as @mentions