From 6f936a707b47e95816e9bcfdbb19cb3da20aec6e Mon Sep 17 00:00:00 2001 From: Will Rossiter Date: Fri, 6 Aug 2021 11:22:27 +1200 Subject: [PATCH] FIX Remove stalled job if implementation not found (#350) * Remove stalled job if implementation not found If a job class is renamed or removed, remove the related stalled jobs rather than throwing an exception (which prevents the rest of the jobs from running). * Handle case if jobDescriptor is deleted. When `refreshDescriptor()` updates $this->descriptor from the database, potentially this object can be null. This change checks to ensure `$this->descriptor` is set before calling any methods. --- src/Jobs/DoormanQueuedJobTask.php | 37 +++++++++++++++++++------------ src/Services/QueuedJobService.php | 7 ++++++ 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/Jobs/DoormanQueuedJobTask.php b/src/Jobs/DoormanQueuedJobTask.php index b3d455c5..0da7ab4f 100644 --- a/src/Jobs/DoormanQueuedJobTask.php +++ b/src/Jobs/DoormanQueuedJobTask.php @@ -18,7 +18,7 @@ class DoormanQueuedJobTask implements Task, Expires, Process, Cancellable protected $id; /** - * @var QueuedJobDescriptor + * @var QueuedJobDescriptor|null */ protected $descriptor; @@ -132,7 +132,7 @@ public function getData() */ public function ignoresRules() { - if ($this->descriptor->hasMethod('ignoreRules')) { + if ($this->descriptor && $this->descriptor->hasMethod('ignoreRules')) { return $this->descriptor->ignoreRules(); } @@ -144,7 +144,7 @@ public function ignoresRules() */ public function stopsSiblings() { - if ($this->descriptor->hasMethod('stopsSiblings')) { + if ($this->descriptor && $this->descriptor->hasMethod('stopsSiblings')) { return $this->descriptor->stopsSiblings(); } @@ -158,7 +158,7 @@ public function stopsSiblings() */ public function getExpiresIn() { - if ($this->descriptor->hasMethod('getExpiresIn')) { + if ($this->descriptor && $this->descriptor->hasMethod('getExpiresIn')) { return $this->descriptor->getExpiresIn(); } @@ -173,7 +173,7 @@ public function getExpiresIn() */ public function shouldExpire($startedAt) { - if ($this->descriptor->hasMethod('shouldExpire')) { + if ($this->descriptor && $this->descriptor->hasMethod('shouldExpire')) { return $this->descriptor->shouldExpire($startedAt); } @@ -188,14 +188,19 @@ public function shouldExpire($startedAt) public function canRunTask() { $this->refreshDescriptor(); - return in_array( - $this->descriptor->JobStatus, - array( - QueuedJob::STATUS_NEW, - QueuedJob::STATUS_INIT, - QueuedJob::STATUS_WAIT - ) - ); + + if ($this->descriptor) { + return in_array( + $this->descriptor->JobStatus, + array( + QueuedJob::STATUS_NEW, + QueuedJob::STATUS_INIT, + QueuedJob::STATUS_WAIT + ) + ); + } + + return false; } /** @@ -213,6 +218,10 @@ public function isCancelled() QueuedJob::STATUS_COMPLETE, ]; - return in_array($this->descriptor->JobStatus, $cancelledStates, true); + if ($this->descriptor) { + return in_array($this->descriptor->JobStatus, $cancelledStates, true); + } + + return true; } } diff --git a/src/Services/QueuedJobService.php b/src/Services/QueuedJobService.php index 271f197f..7e1625ad 100644 --- a/src/Services/QueuedJobService.php +++ b/src/Services/QueuedJobService.php @@ -470,6 +470,13 @@ public function checkJobHealth($queue = null) /** @var QueuedJobDescriptor $stalledJob */ foreach ($stalledJobs as $stalledJob) { $jobClass = $stalledJob->Implementation; + + if (!class_exists($jobClass)) { + $stalledJob->delete(); + + continue; + } + $jobSingleton = singleton($jobClass); if ($jobSingleton instanceof RunBuildTaskJob) {