Skip to content

Commit 1cf8ba5

Browse files
author
Anton Evers
committed
Remove scheduled jobs that do not match their cron expression
When you change a cron expression in the config, you do not want jobs that were scheduled ahead to be executed on the old config cron expression. The cleanup makes the config change take immediate effect.
1 parent 48f8ca4 commit 1cf8ba5

File tree

1 file changed

+48
-9
lines changed

1 file changed

+48
-9
lines changed

app/code/Magento/Cron/Observer/ProcessCronQueueObserver.php

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,17 @@ class ProcessCronQueueObserver implements ObserverInterface
109109
/**
110110
* @var \Psr\Log\LoggerInterface
111111
*/
112-
private $logger;
112+
protected $logger;
113113

114114
/**
115115
* @var \Magento\Framework\App\State
116116
*/
117-
private $state;
117+
protected $state;
118+
119+
/**
120+
* @var array
121+
*/
122+
protected $invalid = [];
118123

119124
/**
120125
* @param \Magento\Framework\ObjectManagerInterface $objectManager
@@ -180,15 +185,17 @@ public function execute(\Magento\Framework\Event\Observer $observer)
180185
$this->generate($groupId);
181186
if ($this->request->getParam('group') !== null
182187
&& $this->request->getParam('group') !== '\'' . ($groupId) . '\''
183-
&& $this->request->getParam('group') !== $groupId) {
188+
&& $this->request->getParam('group') !== $groupId
189+
) {
184190
continue;
185191
}
186192
if (($this->request->getParam(self::STANDALONE_PROCESS_STARTED) !== '1') && (
187193
$this->scopeConfig->getValue(
188194
'system/cron/' . $groupId . '/use_separate_process',
189195
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
190196
) == 1
191-
)) {
197+
)
198+
) {
192199
$this->shell->execute(
193200
$phpPath . ' %s cron:run --group=' . $groupId . ' --' . Cli::INPUT_KEY_BOOTSTRAP . '='
194201
. self::STANDALONE_PROCESS_STARTED . '=1',
@@ -336,7 +343,9 @@ public function generate($groupId)
336343
* generate global crontab jobs
337344
*/
338345
$jobs = $this->config->getJobs();
346+
$this->invalid = [];
339347
$this->generateJobs($jobs[$groupId], $exists, $groupId);
348+
$this->cleanupScheduleMismatches();
340349

341350
/**
342351
* save time schedules generation was ran with no expiration
@@ -469,13 +478,20 @@ public function saveSchedule($jobCode, $cronExpression, $timeInterval, $exists)
469478
$currentTime = $this->timezone->scopeTimeStamp();
470479
$timeAhead = $currentTime + $timeInterval;
471480
for ($time = $currentTime; $time < $timeAhead; $time += self::SECONDS_IN_MINUTE) {
472-
$timestamp = strftime('%Y-%m-%d %H:%M:00', $time);
473-
if (!empty($exists[$jobCode . '/' . $timestamp])) {
474-
// already scheduled
481+
$scheduledAt = strftime('%Y-%m-%d %H:%M:00', $time);
482+
$alreadyScheduled = !empty($exists[$jobCode . '/' . $scheduledAt]);
483+
$schedule = $this->generateSchedule($jobCode, $cronExpression, $time);
484+
$valid = $schedule->trySchedule();
485+
if (!$valid) {
486+
if ($alreadyScheduled) {
487+
if (!isset($this->invalid[$jobCode])) {
488+
$this->invalid[$jobCode] = [];
489+
}
490+
$this->invalid[$jobCode][] = $scheduledAt;
491+
}
475492
continue;
476493
}
477-
$schedule = $this->generateSchedule($jobCode, $cronExpression, $time);
478-
if ($schedule->trySchedule()) {
494+
if (!$alreadyScheduled) {
479495
// time matches cron expression
480496
$schedule->save();
481497
}
@@ -516,6 +532,9 @@ public function getScheduleTimeInterval($groupId)
516532
}
517533

518534
/**
535+
* Clean up scheduled jobs that are disabled in the configuration
536+
* This can happen when you turn off a cron job in the config and flush the cache
537+
*
519538
* @param $groupId
520539
*/
521540
public function cleanupDisabledJobs($groupId)
@@ -551,4 +570,24 @@ public function getCronExpression($jobConfig)
551570
}
552571
return $cronExpression;
553572
}
573+
574+
/**
575+
* Clean up scheduled jobs that do not match their cron expression anymore
576+
* This can happen when you change the cron expression and flush the cache
577+
*
578+
* @return $this
579+
*/
580+
public function cleanupScheduleMismatches()
581+
{
582+
foreach ($this->invalid as $jobCode => $scheduledAtList) {
583+
/** @var \Magento\Cron\Model\ResourceModel\Schedule $scheduleResource */
584+
$scheduleResource = $this->scheduleFactory->create()->getResource();
585+
$scheduleResource->getConnection()->delete($scheduleResource->getMainTable(), [
586+
'status=?' => Schedule::STATUS_PENDING,
587+
'job_code=?' => $jobCode,
588+
'scheduled_at in (?)' => $scheduledAtList,
589+
]);
590+
}
591+
return $this;
592+
}
554593
}

0 commit comments

Comments
 (0)