From 41cbd0ba40a906cd47c3d57024b0da27324e7ebb Mon Sep 17 00:00:00 2001 From: Dan Wallis Date: Mon, 14 Mar 2022 10:37:06 +0000 Subject: [PATCH] Retry jobs which fail or have gone missing --- Model/CleanRunningJobs.php | 23 ++++++++++ Plugin/Cron/Model/ScheduleResourcePlugin.php | 27 +++++++++-- Scope/Config.php | 47 ++++++++++++++++++++ etc/adminhtml/system.xml | 14 ++++++ etc/config.xml | 4 +- 5 files changed, 110 insertions(+), 5 deletions(-) create mode 100644 Scope/Config.php diff --git a/Model/CleanRunningJobs.php b/Model/CleanRunningJobs.php index ef163c29..7c67761b 100644 --- a/Model/CleanRunningJobs.php +++ b/Model/CleanRunningJobs.php @@ -5,8 +5,10 @@ use EthanYehuda\CronjobManager\Api\Data\ScheduleInterface; use EthanYehuda\CronjobManager\Api\ScheduleRepositoryAdapterInterface; +use EthanYehuda\CronjobManager\Scope\Config; use Magento\Cron\Model\ResourceModel\Schedule\CollectionFactory; use Magento\Cron\Model\Schedule; +use Magento\Cron\Model\ScheduleFactory; use Magento\Framework\Stdlib\DateTime\DateTime; /** @@ -14,10 +16,17 @@ */ class CleanRunningJobs { + /** @var Config */ + private $config; + /** * @var ProcessManagement */ private $processManagement; + + /** @var ScheduleFactory */ + private $scheduleFactory; + /** * @var ScheduleRepositoryAdapterInterface */ @@ -32,11 +41,15 @@ class CleanRunningJobs private $dateTime; public function __construct( + Config $config, + ScheduleFactory $scheduleFactory, ScheduleRepositoryAdapterInterface $scheduleRepository, ProcessManagement $processManagement, DateTime $dateTime, Clock $clock ) { + $this->config = $config; + $this->scheduleFactory = $scheduleFactory; $this->processManagement = $processManagement; $this->scheduleRepository = $scheduleRepository; $this->dateTime = $dateTime; @@ -73,6 +86,16 @@ public function execute() ->setMessages(implode("\n", $messages)); $this->scheduleRepository->save($schedule); + + // We check 'scheduled_at' to avoid scheduling jobs run via command line + if ($schedule->getScheduledAt() && $this->config->isRetryJobsGoneAway()) { + $this->scheduleFactory->create() + ->setJobCode($schedule->getJobCode()) + ->setStatus(Schedule::STATUS_PENDING) + ->setCreatedAt(strftime('%Y-%m-%d %H:%M:%S')) + ->setScheduledAt(strftime('%Y-%m-%d %H:%M:%S')) + ->save(); + } } } } diff --git a/Plugin/Cron/Model/ScheduleResourcePlugin.php b/Plugin/Cron/Model/ScheduleResourcePlugin.php index 4781fd83..2050d605 100644 --- a/Plugin/Cron/Model/ScheduleResourcePlugin.php +++ b/Plugin/Cron/Model/ScheduleResourcePlugin.php @@ -4,24 +4,33 @@ namespace EthanYehuda\CronjobManager\Plugin\Cron\Model; use EthanYehuda\CronjobManager\Model\ErrorNotification; -use Magento\Cron\Model\ConfigInterface; +use EthanYehuda\CronjobManager\Scope\Config; use Magento\Cron\Model\ResourceModel\Schedule as ScheduleResource; use Magento\Cron\Model\Schedule; +use Magento\Cron\Model\ScheduleFactory; use Magento\Framework\DataObject; class ScheduleResourcePlugin { + /** @var Config */ + private $config; + /** * @var ErrorNotification */ private $errorNotification; + /** @var ScheduleFactory */ + private $scheduleFactory; + public function __construct( - ConfigInterface $config, - ErrorNotification $errorNotification + Config $config, + ErrorNotification $errorNotification, + ScheduleFactory $scheduleFactory ) { $this->config = $config; $this->errorNotification = $errorNotification; + $this->scheduleFactory = $scheduleFactory; } public function beforeSave( @@ -72,7 +81,7 @@ protected function recordJobGroup(DataObject $dataObject): void } /** - * Email notification if status has been set to ERROR + * Email notification and job retry if status has been set to ERROR */ public function afterSave( ScheduleResource $subject, @@ -83,6 +92,16 @@ public function afterSave( && $object->getStatus() === Schedule::STATUS_ERROR ) { $this->errorNotification->sendFor($object); + + // We check 'scheduled_at' to avoid scheduling jobs run via command line + if ($object->getScheduledAt() && $this->config->isRetryFailedJobs()) { + $this->scheduleFactory->create() + ->setJobCode($object->getJobCode()) + ->setStatus(Schedule::STATUS_PENDING) + ->setCreatedAt(strftime('%Y-%m-%d %H:%M:%S')) + ->setScheduledAt(strftime('%Y-%m-%d %H:%M:%S')) + ->save(); + } } return $result; } diff --git a/Scope/Config.php b/Scope/Config.php new file mode 100644 index 00000000..ab9ae005 --- /dev/null +++ b/Scope/Config.php @@ -0,0 +1,47 @@ +magentoConfig = $magentoConfig; + $this->scopeConfig = $scopeConfig; + } + + public function getJobs():array + { + return $this->magentoConfig->getJobs(); + } + + public function isRetryFailedJobs(): bool + { + return $this->scopeConfig->isSetFlag(self::RETRY_FAILED_JOBS); + } + + public function isRetryJobsGoneAway(): bool + { + if ($this->isRetryFailedJobs()) { + // If we are to retry all jobs, then we don't also want to retry + // jobs which have been detected as missing/gone away. Doing so + // would create duplicate entries in the schedule. + return false; + } + + return $this->scopeConfig->isSetFlag(self::RETRY_JOBS_GONE_AWAY); + } +} diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index 8b7e7246..7c004845 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -10,6 +10,15 @@ Magento\Config\Model\Config\Source\Yesno If a process has status "running", but there is no corresponding process alive on the server, the job will be set to "error". This prevents buildup of false "running" jobs. + + + When enabled, any jobs which have been detected as missing (see above) will be scheduled anew for immediate execution + Magento\Config\Model\Config\Source\Yesno + + 1 + 0 + + Magento\Config\Model\Config\Source\Yesno @@ -35,6 +44,11 @@ 1 + + + When enabled, any jobs which result in an "error" status will be scheduled anew for immediate execution + Magento\Config\Model\Config\Source\Yesno + diff --git a/etc/config.xml b/etc/config.xml index 139bae99..d944a9fd 100644 --- a/etc/config.xml +++ b/etc/config.xml @@ -9,7 +9,9 @@ general system_cron_job_manager_email_template + 0 + 1 - \ No newline at end of file +