From 2ba0033afd1aa22baf98d6fff19842f70f1e28e2 Mon Sep 17 00:00:00 2001 From: Holger Brunn Date: Fri, 14 May 2021 15:37:20 +0200 Subject: [PATCH 1/2] [IMP] queue_job: Add cancelled state to queue.job --- queue_job/job.py | 16 ++++++++++++++ queue_job/models/queue_job.py | 29 ++++++++++++++++++++++-- queue_job/views/queue_job_views.xml | 34 ++++++++++++++++++++++++++++- 3 files changed, 76 insertions(+), 3 deletions(-) diff --git a/queue_job/job.py b/queue_job/job.py index c121e16eef..2045bf8362 100644 --- a/queue_job/job.py +++ b/queue_job/job.py @@ -19,6 +19,7 @@ PENDING = 'pending' ENQUEUED = 'enqueued' +CANCELLED = 'cancelled' DONE = 'done' STARTED = 'started' FAILED = 'failed' @@ -27,6 +28,7 @@ (ENQUEUED, 'Enqueued'), (STARTED, 'Started'), (DONE, 'Done'), + (CANCELLED, 'Cancelled'), (FAILED, 'Failed')] DEFAULT_PRIORITY = 10 # used by the PriorityQueue to sort the jobs @@ -283,6 +285,9 @@ def _load_from_db_record(cls, job_db_record): if stored.date_done: job_.date_done = stored.date_done + if stored.date_cancelled: + job_.date_cancelled = stored.date_cancelled + job_.state = stored.state job_.result = stored.result if stored.result else None job_.exc_info = stored.exc_info if stored.exc_info else None @@ -435,6 +440,7 @@ def __init__(self, func, self.date_enqueued = None self.date_started = None self.date_done = None + self.date_cancelled = None self.result = None self.exc_name = None @@ -514,6 +520,7 @@ def _store_values(self, create=False): 'date_started': False, 'date_done': False, 'exec_time': False, + 'date_cancelled': False, 'eta': False, 'identity_key': False, "worker_pid": self.worker_pid, @@ -527,6 +534,8 @@ def _store_values(self, create=False): vals['date_done'] = self.date_done if self.exec_time: vals["exec_time"] = self.exec_time + if self.date_cancelled: + vals['date_cancelled'] = self.date_cancelled if self.eta: vals['eta'] = self.eta if self.identity_key: @@ -671,6 +680,7 @@ def set_pending(self, result=None, reset_retry=True): self.date_done = None self.worker_pid = None self.date_done = None + self.date_cancelled = None if reset_retry: self.retry = 0 if result is not None: @@ -695,6 +705,12 @@ def set_done(self, result=None): if result is not None: self.result = result + def set_cancelled(self, result=None): + self.state = CANCELLED + self.date_cancelled = datetime.now() + if result is not None: + self.result = result + def set_failed(self, **kw): self.state = FAILED for k, v in kw.items(): diff --git a/queue_job/models/queue_job.py b/queue_job/models/queue_job.py index d58744f387..3986688aa3 100644 --- a/queue_job/models/queue_job.py +++ b/queue_job/models/queue_job.py @@ -11,7 +11,7 @@ from odoo.osv import expression from ..fields import JobSerialized -from ..job import DONE, PENDING, STATES, Job +from ..job import CANCELLED, DONE, PENDING, STATES, Job _logger = logging.getLogger(__name__) @@ -91,6 +91,7 @@ class QueueJob(models.Model): group_operator="avg", help="Time required to execute this job in seconds. Average when grouped.", ) + date_cancelled = fields.Datetime(readonly=True) eta = fields.Datetime(string='Execute only after') retry = fields.Integer(string='Current try') @@ -200,6 +201,8 @@ def _change_job_state(self, state, result=None): job_.set_done(result=result) elif state == PENDING: job_.set_pending(result=result) + elif state == CANCELLED: + job_.set_cancelled(result=result) else: raise ValueError('State not supported: %s' % state) job_.store() @@ -210,6 +213,12 @@ def button_done(self): self._change_job_state(DONE, result=result) return True + @api.multi + def button_cancelled(self): + result = _('Cancelled by %s') % self.env.user.name + self._change_job_state(CANCELLED, result=result) + return True + @api.multi def requeue(self): self._change_job_state(PENDING) @@ -271,7 +280,9 @@ def autovacuum(self): deadline = datetime.now() - timedelta( days=int(channel.removal_interval)) jobs = self.search( - [('date_done', '<=', deadline), + ['|', + ('date_done', '<=', deadline), + ('date_cancelled', '<=', deadline), ('channel', '=', channel.complete_name)], ) if jobs: @@ -400,6 +411,20 @@ def set_done(self): return {'type': 'ir.actions.act_window_close'} +class SetJobsToCancelled(models.TransientModel): + _inherit = 'queue.requeue.job' + _name = 'queue.jobs.to.cancelled' + _description = 'Cancel all selected jobs' + + @api.multi + def set_cancelled(self): + jobs = self.job_ids.filtered( + lambda x: x.state in ('pending', 'failed', 'enqueued') + ) + jobs.button_cancelled() + return {'type': 'ir.actions.act_window_close'} + + class JobChannel(models.Model): _name = 'queue.job.channel' _description = 'Job Channels' diff --git a/queue_job/views/queue_job_views.xml b/queue_job/views/queue_job_views.xml index b8e4d33fe5..c598c992eb 100644 --- a/queue_job/views/queue_job_views.xml +++ b/queue_job/views/queue_job_views.xml @@ -20,6 +20,12 @@ string="Set to 'Done'" type="object" groups="queue_job.group_queue_job_manager"/> +