From 2486259ef99ec85cf1c0a8200e31d350c582fd4c Mon Sep 17 00:00:00 2001 From: Enric Tobella Date: Thu, 25 Jul 2019 12:58:10 +0000 Subject: [PATCH] [IMP] base: reduced number of checks on module loading If you have a module with several dependencies or a complex dependency graph, the system repeats the number of checks of a module. For example: we have 4 modules A, B, C and D, where A depends on B and C, B depends on D and C depends on D. Before this patch, we check once if A is installed, once if B is installed, once if C is installed and twice id D is installed. With this patch, D is checked only once. On this example, the difference is minimal but on worse scenario as explained on the below issue, the processing time was provoking a timeout on test platform https://github.com/odoo/odoo/pull/29779#issuecomment-452821082 Cherry-pick to master of #29779 closes odoo/odoo#35185 Signed-off-by: Martin Trigaux (mat) --- odoo/addons/base/models/ir_module.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/odoo/addons/base/models/ir_module.py b/odoo/addons/base/models/ir_module.py index 8c42335a056..883c8a43784 100644 --- a/odoo/addons/base/models/ir_module.py +++ b/odoo/addons/base/models/ir_module.py @@ -338,35 +338,38 @@ class Module(models.Model): msg = _('Unable to process module "%s" because an external dependency is not met: %s') raise UserError(msg % (module_name, e.args[0])) - def _state_update(self, newstate, states_to_update, level=100): + def _state_update(self, newstate, states_to_update, level=100, checked=False): if level < 1: raise UserError(_('Recursion error in modules dependencies !')) # whether some modules are installed with demo data demo = False - - for module in self: + if not checked: + checked = self.browse() + for module in (self - checked): # determine dependency modules to update/others update_mods, ready_mods = self.browse(), self.browse() for dep in module.dependencies_id: if dep.state == 'unknown': raise UserError(_("You try to install module '%s' that depends on module '%s'.\nBut the latter module is not available in your system.") % (module.name, dep.name,)) if dep.depend_id.state == newstate: - ready_mods += dep.depend_id + ready_mods |= dep.depend_id else: - update_mods += dep.depend_id + update_mods |= dep.depend_id # update dependency modules that require it, and determine demo for module - update_demo = update_mods._state_update(newstate, states_to_update, level=level-1) + update_demo, now_checked = update_mods._state_update( + newstate, states_to_update, level=level-1, checked=checked) module_demo = module.demo or update_demo or any(mod.demo for mod in ready_mods) demo = demo or module_demo + checked |= now_checked # check dependencies and update module itself self.check_external_dependencies(module.name, newstate) if module.state in states_to_update: module.write({'state': newstate, 'demo': module_demo}) - return demo + return demo, checked | self @assert_log_admin_access def button_install(self):