From 82e8c74f1e5a3036b237cf514d69e3f80d5d5894 Mon Sep 17 00:00:00 2001 From: Stanislas Sobieski Date: Thu, 8 Sep 2022 15:21:00 +0000 Subject: [PATCH] [FIX] base: avoid indexing attachment on copy When sending a mass mailing with a pdf attachment, the ir.attachment is copied in the mail.composer for each email. Spending time and resources in the indexing of the pdf. On copy that value is already in the vals. This is especially true when attachment_indexation is installed, processing the pdf documents can be costly with pdfminer. It could also be done by overwriting the copu from ir_attachment but it could happen a misuse of mass create of ir.attachment with the same file has the same issue closes odoo/odoo#100374 X-original-commit: 3d59cc849ed1040c08c4d1488866ba78c80990c8 Signed-off-by: Raphael Collet --- .../models/ir_attachment.py | 18 +++++++++++++++--- odoo/addons/base/models/ir_attachment.py | 13 +++++++++---- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/addons/attachment_indexation/models/ir_attachment.py b/addons/attachment_indexation/models/ir_attachment.py index c6017f010c8..164ef46e800 100644 --- a/addons/attachment_indexation/models/ir_attachment.py +++ b/addons/attachment_indexation/models/ir_attachment.py @@ -6,6 +6,7 @@ import xml.dom.minidom import zipfile from odoo import api, models +from odoo.tools.lru import LRU _logger = logging.getLogger(__name__) @@ -21,6 +22,8 @@ except ImportError: FTYPES = ['docx', 'pptx', 'xlsx', 'opendoc', 'pdf'] +index_content_cache = LRU(1) + def textToString(element): buff = u"" for node in element.childNodes: @@ -121,10 +124,19 @@ class IrAttachment(models.Model): return buf @api.model - def _index(self, bin_data, mimetype): + def _index(self, bin_data, mimetype, checksum=None): + if checksum: + cached_content = index_content_cache.get(checksum) + if cached_content: + return cached_content + res = False for ftype in FTYPES: buf = getattr(self, '_index_%s' % ftype)(bin_data) if buf: - return buf.replace('\x00', '') + res = buf.replace('\x00', '') + break - return super(IrAttachment, self)._index(bin_data, mimetype) + res = res or super(IrAttachment, self)._index(bin_data, mimetype, checksum=checksum) + if checksum: + index_content_cache[checksum] = res + return res diff --git a/odoo/addons/base/models/ir_attachment.py b/odoo/addons/base/models/ir_attachment.py index b881cc49f85..11cbbc96871 100644 --- a/odoo/addons/base/models/ir_attachment.py +++ b/odoo/addons/base/models/ir_attachment.py @@ -251,10 +251,15 @@ class IrAttachment(models.Model): self._file_delete(fname) def _get_datas_related_values(self, data, mimetype): + checksum = self._compute_checksum(data) + try: + index_content = self._index(data, mimetype, checksum=checksum) + except TypeError: + index_content = self._index(data, mimetype) values = { 'file_size': len(data), - 'checksum': self._compute_checksum(data), - 'index_content': self._index(data, mimetype), + 'checksum': checksum, + 'index_content': index_content, 'store_fname': False, 'db_datas': data, } @@ -360,7 +365,7 @@ class IrAttachment(models.Model): return values @api.model - def _index(self, bin_data, file_type): + def _index(self, bin_data, file_type, checksum=None): """ compute the index content of the given binary data. This is a python implementation of the unix command 'strings'. :param bin_data : datas in binary form @@ -652,7 +657,7 @@ class IrAttachment(models.Model): )) # 'check()' only uses res_model and res_id from values, and make an exists. - # We can group the values by model, res_id to make only one query when + # We can group the values by model, res_id to make only one query when # creating multiple attachments on a single record. record_tuple = (values.get('res_model'), values.get('res_id')) record_tuple_set.add(record_tuple)