From 9150c3d2c9b3e0af241cb45f710bfcb59d9cb7a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Theys?= Date: Wed, 26 Jun 2019 11:24:08 +0000 Subject: [PATCH] [IMP] mail: improve performance of Followers _invalidate_documents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If `self` contains around 1000 records, this reduces the time of the method by a factor of 10 when `read` is necessary, and by 200 when using the values from `vals_list` and no additional query is needed at all. This speeds up the creation of all models using `mail.thread`. Part of task-1918881 closes odoo/odoo#34274 Signed-off-by: Xavier Dollé (xdo) --- addons/mail/models/mail_followers.py | 36 ++++++++++++++++------------ 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/addons/mail/models/mail_followers.py b/addons/mail/models/mail_followers.py index f4f16c2e9f0..1b5c94972c2 100644 --- a/addons/mail/models/mail_followers.py +++ b/addons/mail/models/mail_followers.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from collections import defaultdict import itertools from odoo import api, fields, models @@ -35,21 +36,25 @@ class Followers(models.Model): 'mail.message.subtype', string='Subtype', help="Message subtypes followed, meaning subtypes that will be pushed onto the user's Wall.") - # - # Modifying followers change access rights to individual documents. As the - # cache may contain accessible/inaccessible data, one has to refresh it. - # @api.multi - def _invalidate_documents(self): - """ Invalidate the cache of the documents followed by ``self``. """ - for record in self: - if record.res_id: - self.env[record.res_model].invalidate_cache(ids=[record.res_id]) + def _invalidate_documents(self, vals_list=None): + """ Invalidate the cache of the documents followed by ``self``. + + Modifying followers change access rights to individual documents. As the + cache may contain accessible/inaccessible data, one has to refresh it. + """ + to_invalidate = defaultdict(list) + for record in (vals_list or [{'res_model': rec.res_model, 'res_id': rec.res_id} for rec in self]): + if record.get('res_id'): + to_invalidate[record.get('res_model')].append(record.get('res_id')) + # invalidate in batch for performance + for res_model, res_ids in to_invalidate.items(): + self.env[res_model].invalidate_cache(ids=res_ids) @api.model_create_multi def create(self, vals_list): res = super(Followers, self).create(vals_list) - res._invalidate_documents() + res._invalidate_documents(vals_list) return res @api.multi @@ -240,11 +245,12 @@ GROUP BY fol.id%s""" % ( new, upd = self._add_default_followers(res_model, res_ids, partner_ids, channel_ids, customer_ids=customer_ids) else: new, upd = self._add_followers(res_model, res_ids, partner_ids, partner_subtypes, channel_ids, channel_subtypes, check_existing=check_existing, existing_policy=existing_policy) - sudo_self.create([ - dict(values, res_id=res_id) - for res_id, values_list in new.items() - for values in values_list - ]) + if new: + sudo_self.create([ + dict(values, res_id=res_id) + for res_id, values_list in new.items() + for values in values_list + ]) for fol_id, values in upd.items(): sudo_self.browse(fol_id).write(values)