From 15174e9a70b07f95356bf0a75887e2a02b33baab Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Thu, 17 Jul 2014 17:18:14 +0200 Subject: [PATCH] [IMP] base, mail: cache user.has_group() + ir.ui.menu.load*() Loading the menus is the most expensive operation for an average page load, and the result does not change often. The menu filtering already uses a separate cache based on groups, but the rest of the loading includes reading actions and translating menu names, which is also expensive. Added a cache keyed on user + user lang, plus relevant cache invalidation when any of the following are touched: access rights, user data including groups and language, menus or mail.group subscriptions. The menu filtering cache is still useful in parallel has it is invalidated under different conditions. User.has_group() is cheap but still called very often, so it is an easy win as well, and also frequently used when rendering page templates. --- addons/mail/mail_thread.py | 10 ++++++++-- openerp/addons/base/ir/ir_ui_menu.py | 7 +++++++ openerp/addons/base/res/res_users.py | 3 +++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index e4ab8fe3b87..c50e6d082e8 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -1660,7 +1660,10 @@ class mail_thread(osv.AbstractModel): if user_ids is None: user_ids = [uid] partner_ids = [user.partner_id.id for user in self.pool.get('res.users').browse(cr, uid, user_ids, context=context)] - return self.message_subscribe(cr, uid, ids, partner_ids, subtype_ids=subtype_ids, context=context) + result = self.message_subscribe(cr, uid, ids, partner_ids, subtype_ids=subtype_ids, context=context) + if partner_ids and result: + self.pool['ir.ui.menu'].clear_cache() + return result def message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None): """ Add partners to the records followers. """ @@ -1720,7 +1723,10 @@ class mail_thread(osv.AbstractModel): if user_ids is None: user_ids = [uid] partner_ids = [user.partner_id.id for user in self.pool.get('res.users').browse(cr, uid, user_ids, context=context)] - return self.message_unsubscribe(cr, uid, ids, partner_ids, context=context) + result = self.message_unsubscribe(cr, uid, ids, partner_ids, context=context) + if partner_ids and result: + self.pool['ir.ui.menu'].clear_cache() + return result def message_unsubscribe(self, cr, uid, ids, partner_ids, context=None): """ Remove partners from the records followers. """ diff --git a/openerp/addons/base/ir/ir_ui_menu.py b/openerp/addons/base/ir/ir_ui_menu.py index d55451dd33c..45f1b813457 100644 --- a/openerp/addons/base/ir/ir_ui_menu.py +++ b/openerp/addons/base/ir/ir_ui_menu.py @@ -53,6 +53,8 @@ class ir_ui_menu(osv.osv): # but since we do not use it, set it by ourself. self.pool._any_cache_cleared = True self._menu_cache.clear() + self.load_menus_root._orig.clear_cache(self) + self.load_menus._orig.clear_cache(self) @api.multi @api.returns('self') @@ -352,6 +354,8 @@ class ir_ui_menu(osv.osv): menu_domain = [('parent_id', '=', False)] return self.search(cr, uid, menu_domain, context=context) + @api.cr_uid_context + @tools.ormcache_context(accepted_keys=('lang',)) def load_menus_root(self, cr, uid, context=None): fields = ['name', 'sequence', 'parent_id', 'action'] menu_root_ids = self.get_user_roots(cr, uid, context=context) @@ -364,6 +368,9 @@ class ir_ui_menu(osv.osv): 'all_menu_ids': menu_root_ids, } + + @api.cr_uid_context + @tools.ormcache_context(accepted_keys=('lang',)) def load_menus(self, cr, uid, context=None): """ Loads all menu items (all applications and their sub-menus). diff --git a/openerp/addons/base/res/res_users.py b/openerp/addons/base/res/res_users.py index f81ac0ccccb..5f2ad711ffe 100644 --- a/openerp/addons/base/res/res_users.py +++ b/openerp/addons/base/res/res_users.py @@ -126,6 +126,7 @@ class res_groups(osv.osv): _('The name of the group can not start with "-"')) res = super(res_groups, self).write(cr, uid, ids, vals, context=context) self.pool['ir.model.access'].call_cache_clearing_methods(cr) + self.pool['res.users'].has_group.clear_cache(self.pool['res.users']) return res class res_users(osv.osv): @@ -329,6 +330,7 @@ class res_users(osv.osv): if id in self._uid_cache[db]: del self._uid_cache[db][id] self.context_get.clear_cache(self) + self.has_group.clear_cache(self) return res def unlink(self, cr, uid, ids, context=None): @@ -511,6 +513,7 @@ class res_users(osv.osv): 'target': 'new', } + @tools.ormcache(skiparg=2) def has_group(self, cr, uid, group_ext_id): """Checks whether user belongs to given group.