From dec397b86da3f4e0d67735ed132a3bdf3705d702 Mon Sep 17 00:00:00 2001 From: Julien Castiaux Date: Thu, 21 Nov 2019 13:44:16 +0000 Subject: [PATCH] [IMP] base_automation: refine CRON frequency The current 'Base Action Rule: check and execute' CRON search every four hours for delayed actions to run. This mean, any action scheduled later can be delayed up to four hours. We now dynamically reset the CRON frequency according to the least delayed automated action to minimize the potential gap. closes odoo/odoo#40633 Task: 1998809 Signed-off-by: Raphael Collet (rco) --- .../base_automation/models/base_automation.py | 42 +++++++++++++++++-- .../views/base_automation_view.xml | 5 +++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/addons/base_automation/models/base_automation.py b/addons/base_automation/models/base_automation.py index 3695a82f55c..17be94a5664 100644 --- a/addons/base_automation/models/base_automation.py +++ b/addons/base_automation/models/base_automation.py @@ -25,6 +25,14 @@ DATE_RANGE_FUNCTION = { False: lambda interval: relativedelta(0), } +DATE_RANGE_FACTOR = { + 'minutes': 1, + 'hour': 60, + 'day': 24 * 60, + 'month': 30 * 24 * 60, + False: 0, +} + class BaseAutomation(models.Model): _name = 'base.automation' @@ -64,9 +72,11 @@ class BaseAutomation(models.Model): trigger_field_ids = fields.Many2many('ir.model.fields', string='Trigger Fields', help="The action will be triggered if and only if one of these fields is updated." "If empty, all fields are watched.") + least_delay_msg = fields.Char(compute='_compute_least_delay_msg') - # which fields have an impact on the registry + # which fields have an impact on the registry and the cron CRITICAL_FIELDS = ['model_id', 'active', 'trigger', 'on_change_field_ids'] + RANGE_FIELDS = ['trg_date_range', 'trg_date_range_type'] @api.onchange('model_id') def onchange_model_id(self): @@ -109,6 +119,8 @@ class BaseAutomation(models.Model): if set(vals).intersection(self.CRITICAL_FIELDS): self._update_cron() self._update_registry() + elif set(vals).intersection(self.RANGE_FIELDS): + self._update_cron() return res def unlink(self): @@ -119,10 +131,18 @@ class BaseAutomation(models.Model): def _update_cron(self): """ Activate the cron job depending on whether there exists action rules - based on time conditions. + based on time conditions. Also update its frequency according to + the smallest action delay, or restore the default 4 hours if there + is no time based action. """ cron = self.env.ref('base_automation.ir_cron_data_base_automation_check', raise_if_not_found=False) - return cron and cron.toggle(model=self._name, domain=[('trigger', '=', 'on_time')]) + if cron: + actions = self.with_context(active_test=True).search([('trigger', '=', 'on_time')]) + cron.try_write({ + 'active': bool(actions), + 'interval_type': 'minutes', + 'interval_number': self._get_cron_interval(actions), + }) def _update_registry(self): """ Update the registry after a modification on action rules. """ @@ -154,6 +174,22 @@ class BaseAutomation(models.Model): 'user': self.env.user, } + def _get_cron_interval(self, actions=None): + """ Return the expected time interval used by the cron, in minutes. """ + def get_delay(rec): + return rec.trg_date_range * DATE_RANGE_FACTOR[rec.trg_date_range_type] + + if actions is None: + actions = self.with_context(active_test=True).search([('trigger', '=', 'on_time')]) + + # Minimum 1 minute, maximum 4 hours, 10% tolerance + delay = min(actions.mapped(get_delay), default=0) + return min(max(1, delay // 10), 4 * 60) if delay else 4 * 60 + + def _compute_least_delay_msg(self): + msg = _("Note that this action can be trigged up to %d minutes after its schedule.") + self.least_delay_msg = msg % self._get_cron_interval() + def _filter_pre(self, records): """ Filter the records that satisfy the precondition of action ``self``. """ if self.filter_pre_domain and records: diff --git a/addons/base_automation/views/base_automation_view.xml b/addons/base_automation/views/base_automation_view.xml index 197459957fd..317ddfd8e3b 100644 --- a/addons/base_automation/views/base_automation_view.xml +++ b/addons/base_automation/views/base_automation_view.xml @@ -66,6 +66,11 @@ + + +