Skip to content
Snippets Groups Projects
  • Ivan Yelizariev's avatar
    d17c20e2
    [FIX] mail: speed up read_progress_bar · d17c20e2
    Ivan Yelizariev authored
    
    This commit fixes the performance issue in getting statistics for
    ``activity_state`` (colored clock icon for overdue/today/planned) in
    CRM.  The query has been tested for several years on a large database
    (Odoo's own production database).
    
    Performance test on 29 K crm.lead records (activity_state):
    
    With a filter for 10 records:
    
    ```
    | measurement        | before | after |
    |--------------------+--------+-------|
    | number of queries  |     25 |     5 |
    | query time, ms     |     12 |    95 | (*)
    | remaining time, ms |     32 |     7 |
    ```
    
    All records:
    
    ```
    | measurement        | before | after |
    |--------------------+--------+-------|
    | number of queries  |   1326 |     5 |
    | query time, ms     |   1739 |   129 |
    | remaining time, ms |  47934 |    17 |
    ```
    
    As we can see in the last results, the time went from almost 50 seconds
    (not responsive at all) to 150 milliseconds (responsive).  The time
    increase in (*) may be caused by imperfect measurements, which are raw
    and not averaged measures.
    
    ---
    
    opw-2346901
    task-1915411
    
    closes odoo/odoo#67004
    
    Signed-off-by: default avatarRaphael Collet (rco) <rco@openerp.com>
    Co-authored-by: default avatarNicolas Seinlet <nse@odoo.com>
    d17c20e2
    History
    [FIX] mail: speed up read_progress_bar
    Ivan Yelizariev authored
    
    This commit fixes the performance issue in getting statistics for
    ``activity_state`` (colored clock icon for overdue/today/planned) in
    CRM.  The query has been tested for several years on a large database
    (Odoo's own production database).
    
    Performance test on 29 K crm.lead records (activity_state):
    
    With a filter for 10 records:
    
    ```
    | measurement        | before | after |
    |--------------------+--------+-------|
    | number of queries  |     25 |     5 |
    | query time, ms     |     12 |    95 | (*)
    | remaining time, ms |     32 |     7 |
    ```
    
    All records:
    
    ```
    | measurement        | before | after |
    |--------------------+--------+-------|
    | number of queries  |   1326 |     5 |
    | query time, ms     |   1739 |   129 |
    | remaining time, ms |  47934 |    17 |
    ```
    
    As we can see in the last results, the time went from almost 50 seconds
    (not responsive at all) to 150 milliseconds (responsive).  The time
    increase in (*) may be caused by imperfect measurements, which are raw
    and not averaged measures.
    
    ---
    
    opw-2346901
    task-1915411
    
    closes odoo/odoo#67004
    
    Signed-off-by: default avatarRaphael Collet (rco) <rco@openerp.com>
    Co-authored-by: default avatarNicolas Seinlet <nse@odoo.com>
test_mail_models.py 4.52 KiB
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo import api, fields, models


class MailTestSimple(models.Model):
    """ A very simple model only inheriting from mail.thread when only
    communication history is necessary. """
    _description = 'Simple Chatter Model'
    _name = 'mail.test.simple'
    _inherit = ['mail.thread']

    name = fields.Char()
    email_from = fields.Char()


class MailTestStandard(models.Model):
    """ This model can be used in tests when automatic subscription and simple
    tracking is necessary. Most features are present in a simple way. """
    _description = 'Standard Chatter Model'
    _name = 'mail.test.track'
    _inherit = ['mail.thread']

    name = fields.Char()
    email_from = fields.Char()
    user_id = fields.Many2one('res.users', 'Responsible', track_visibility='onchange')
    umbrella_id = fields.Many2one('mail.test', track_visibility='onchange')
    company_id = fields.Many2one('res.company')


class MailTestActivity(models.Model):
    """ This model can be used to test activities in addition to simple chatter
    features. """
    _description = 'Activity Model'
    _name = 'mail.test.activity'
    _inherit = ['mail.thread', 'mail.activity.mixin']

    name = fields.Char()
    date = fields.Date()
    email_from = fields.Char()
    active = fields.Boolean(default=True)

    def action_start(self, action_summary):
        return self.activity_schedule(
            'test_mail.mail_act_test_todo',
            summary=action_summary
        )

    def action_close(self, action_feedback):
        self.activity_feedback(['test_mail.mail_act_test_todo'], feedback=action_feedback)


class MailTestFull(models.Model):
    """ This model can be used in tests when complex chatter features are
    required like modeling tasks or tickets. """
    _description = 'Full Chatter Model'
    _name = 'mail.test.full'
    _inherit = ['mail.thread']

    name = fields.Char()
    email_from = fields.Char(track_visibility='always')
    count = fields.Integer(default=1)
    datetime = fields.Datetime(default=fields.Datetime.now)
    mail_template = fields.Many2one('mail.template', 'Template')
    customer_id = fields.Many2one('res.partner', 'Customer', track_visibility='onchange', track_sequence=2)
    user_id = fields.Many2one('res.users', 'Responsible', track_visibility='onchange', track_sequence=1)
    umbrella_id = fields.Many2one('mail.test', track_visibility='onchange')

    def _track_template(self, tracking):
        res = super(MailTestFull, self)._track_template(tracking)
        record = self[0]
        changes, tracking_value_ids = tracking[record.id]
        if 'customer_id' in changes and record.mail_template:
            res['customer_id'] = (record.mail_template, {'composition_mode': 'mass_mail'})
        elif 'datetime' in changes:
            res['datetime'] = ('test_mail.mail_test_full_tracking_view', {'composition_mode': 'mass_mail'})
        return res

    def _track_subtype(self, init_values):
        self.ensure_one()
        if 'umbrella_id' in init_values and self.umbrella_id:
            return 'test_mail.st_mail_test_full_umbrella_upd'
        return super(MailTestFull, self)._track_subtype(init_values)


class MailTestAlias(models.Model):
    """ This model can be used in tests when umbrella records like projects
    or teams are required. """
    _description = 'Alias Chatter Model'
    _name = 'mail.test'
    _mail_post_access = 'read'
    _inherit = ['mail.thread', 'mail.alias.mixin']

    name = fields.Char()
    description = fields.Text()
    customer_id = fields.Many2one('res.partner', 'Customer')
    alias_id = fields.Many2one(
        'mail.alias', 'Alias',
        delegate=True)

    def get_alias_model_name(self, vals):
        return vals.get('alias_model', 'mail.test')

    def get_alias_values(self):
        self.ensure_one()
        res = super(MailTestAlias, self).get_alias_values()
        res['alias_force_thread_id'] = self.id
        res['alias_parent_thread_id'] = self.id
        return res


class MailModel(models.Model):
    _name = 'test_performance.mail'
    _description = 'Test Performance Mail'
    _inherit = 'mail.thread'

    name = fields.Char()
    value = fields.Integer()
    value_pc = fields.Float(compute="_value_pc", store=True)
    track = fields.Char(default='test', track_visibility="onchange")
    partner_id = fields.Many2one('res.partner', string='Customer')

    @api.depends('value')
    def _value_pc(self):
        for record in self:
            record.value_pc = float(record.value) / 100