diff --git a/frappe/core/doctype/rq_job/rq_job.py b/frappe/core/doctype/rq_job/rq_job.py index fd6ef7ce81..93710552dc 100644 --- a/frappe/core/doctype/rq_job/rq_job.py +++ b/frappe/core/doctype/rq_job/rq_job.py @@ -112,6 +112,16 @@ class RQJob(Document): except InvalidJobOperation: frappe.msgprint(_("Job is not running."), title=_("Invalid Operation")) + @check_permissions + def cancel(self): + if self.status == "queued": + self.job.cancel() + else: + frappe.msgprint( + _("Job is in {0} state and can't be cancelled").format(self.status), + title=_("Invalid Operation"), + ) + @staticmethod def get_count(filters=None) -> int: return len(RQJob.get_matching_job_ids(filters)) diff --git a/frappe/core/doctype/rq_job/test_rq_job.py b/frappe/core/doctype/rq_job/test_rq_job.py index 8ae4bc427b..accc6712b8 100644 --- a/frappe/core/doctype/rq_job/test_rq_job.py +++ b/frappe/core/doctype/rq_job/test_rq_job.py @@ -26,6 +26,12 @@ def wait_for_completion(job: Job): class TestRQJob(IntegrationTestCase): BG_JOB = "frappe.core.doctype.rq_job.test_rq_job.test_func" + def setUp(self) -> None: + # Cleanup all pending jobs + for job in frappe.get_all("RQ Job", {"status": "queued"}): + frappe.get_doc("RQ Job", job.name).cancel() + return super().setUp() + def check_status(self, job: Job, status, wait=True): if wait: wait_for_completion(job)