Skip to content
Snippets Groups Projects
Commit bba39fa8 authored by Leloup Loïc (lole)'s avatar Leloup Loïc (lole)
Browse files

[FIX] mail : speed systray_get_activities

When the number of mail.activities for a user was getting too big, the whole database is getting slowed down as the activities are recomputed each time a page is loaded.

The issue was mostly brought by commit [03c3d440](https://github.com/odoo/odoo/commit/03c3d440ae31baa0400b7adba7f6373556ff5c38

).

The time was recorded when refreshing the home page of the site.

|     |     |     |
| --- | --- | --- |
| #activities | before PR | after PR |
| 100 000 on 1 model | 22.66s (single test) | 0.408s (worst of few runs) |
| 40 on 40 models | 0.06s worst, 0.037s best | 0.053s (worst of few) (0.038s best) |

closes odoo/odoo#134126

Signed-off-by: default avatarSébastien Theys (seb) <seb@odoo.com>
parent dacfa844
No related branches found
No related tags found
No related merge requests found
...@@ -117,29 +117,46 @@ GROUP BY channel_moderator.res_users_id""", [tuple(self.ids)]) ...@@ -117,29 +117,46 @@ GROUP BY channel_moderator.res_users_id""", [tuple(self.ids)])
@api.model @api.model
def systray_get_activities(self): def systray_get_activities(self):
activities = self.env["mail.activity"].search([("user_id", "=", self.env.uid)]) query = """SELECT array_agg(res_id) as res_ids, m.id, count(*),
activities_by_record_by_model_name = defaultdict(lambda: defaultdict(lambda: self.env["mail.activity"])) CASE
for activity in activities: WHEN %(today)s::date - act.date_deadline::date = 0 Then 'today'
record = self.env[activity.res_model].browse(activity.res_id) WHEN %(today)s::date - act.date_deadline::date > 0 Then 'overdue'
activities_by_record_by_model_name[activity.res_model][record] += activity WHEN %(today)s::date - act.date_deadline::date < 0 Then 'planned'
model_ids = list({self.env["ir.model"]._get(name).id for name in activities_by_record_by_model_name.keys()}) END AS states
FROM mail_activity AS act
JOIN ir_model AS m ON act.res_model_id = m.id
WHERE user_id = %(user_id)s
GROUP BY m.id, states;
"""
self.env.cr.execute(query, {
'today': fields.Date.context_today(self),
'user_id': self.env.uid,
})
activity_data = self.env.cr.dictfetchall()
records_by_state_by_model = defaultdict(lambda: {"today": set(), "overdue": set(), "planned": set(), "all": set()})
for data in activity_data:
records_by_state_by_model[data["id"]][data["states"]] = set(data["res_ids"])
records_by_state_by_model[data["id"]]["all"] = records_by_state_by_model[data["id"]]["all"] | set(data["res_ids"])
user_activities = {} user_activities = {}
for model_name, activities_by_record in activities_by_record_by_model_name.items(): for model_id in records_by_state_by_model:
domain = [("id", "in", list({r.id for r in activities_by_record.keys()}))] model_dic = records_by_state_by_model[model_id]
allowed_records = self.env[model_name].search(domain) model = self.env["ir.model"].browse(model_id).with_prefetch(tuple(records_by_state_by_model.keys()))
allowed_records = self.env[model.model].search([("id", "in", tuple(model_dic["all"]))])
if not allowed_records: if not allowed_records:
continue continue
module = self.env[model_name]._original_module module = self.env[model.model]._original_module
icon = module and modules.module.get_module_icon(module) icon = module and modules.module.get_module_icon(module)
user_activities[model_name] = { today = len(model_dic["today"] & set(allowed_records.ids))
"name": self.env["ir.model"]._get(model_name).with_prefetch(model_ids).name, overdue = len(model_dic["overdue"] & set(allowed_records.ids))
"model": model_name, user_activities[model.model] = {
"name": model.name,
"model": model.model,
"type": "activity", "type": "activity",
"icon": icon, "icon": icon,
"total_count": 0, "total_count": today + overdue,
"today_count": 0, "today_count": today,
"overdue_count": 0, "overdue_count": overdue,
"planned_count": 0, "planned_count": len(model_dic["planned"] & set(allowed_records.ids)),
"actions": [ "actions": [
{ {
"icon": "fa-clock-o", "icon": "fa-clock-o",
...@@ -147,13 +164,6 @@ GROUP BY channel_moderator.res_users_id""", [tuple(self.ids)]) ...@@ -147,13 +164,6 @@ GROUP BY channel_moderator.res_users_id""", [tuple(self.ids)])
} }
], ],
} }
for record, activities in activities_by_record.items():
if record not in allowed_records:
continue
for activity in activities:
user_activities[model_name]["%s_count" % activity.state] += 1
if activity.state in ("today", "overdue"):
user_activities[model_name]["total_count"] += 1
return list(user_activities.values()) return list(user_activities.values())
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment