Skip to content

Commit e2225fa

Browse files
authored
ENGCOM-5365: [Backport] Added function to check against running/pending/successful cron tasks #23439
2 parents 23ef553 + b196657 commit e2225fa

File tree

2 files changed

+64
-29
lines changed

2 files changed

+64
-29
lines changed

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

Lines changed: 60 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6-
76
/**
87
* Handling cron jobs
98
*/
109
namespace Magento\Cron\Observer;
1110

11+
use Magento\Cron\Model\Schedule;
1212
use Magento\Framework\App\State;
1313
use Magento\Framework\Console\Cli;
1414
use Magento\Framework\Event\ObserverInterface;
15-
use \Magento\Cron\Model\Schedule;
1615
use Magento\Framework\Profiler\Driver\Standard\Stat;
1716
use Magento\Framework\Profiler\Driver\Standard\StatFactory;
1817

@@ -201,7 +200,6 @@ public function __construct(
201200
*/
202201
public function execute(\Magento\Framework\Event\Observer $observer)
203202
{
204-
205203
$currentTime = $this->dateTime->gmtTimestamp();
206204
$jobGroupsRoot = $this->_config->getJobs();
207205
// sort jobs groups to start from used in separated process
@@ -255,7 +253,6 @@ function ($groupId) use ($currentTime, $jobsRoot) {
255253
*/
256254
private function lockGroup($groupId, callable $callback)
257255
{
258-
259256
if (!$this->lockManager->lock(self::LOCK_PREFIX . $groupId, self::LOCK_TIMEOUT)) {
260257
$this->logger->warning(
261258
sprintf(
@@ -290,17 +287,20 @@ protected function _runJob($scheduledTime, $currentTime, $jobConfig, $schedule,
290287
$scheduleLifetime = $scheduleLifetime * self::SECONDS_IN_MINUTE;
291288
if ($scheduledTime < $currentTime - $scheduleLifetime) {
292289
$schedule->setStatus(Schedule::STATUS_MISSED);
290+
// phpcs:ignore Magento2.Exceptions.DirectThrow
293291
throw new \Exception(sprintf('Cron Job %s is missed at %s', $jobCode, $schedule->getScheduledAt()));
294292
}
295293

296294
if (!isset($jobConfig['instance'], $jobConfig['method'])) {
297295
$schedule->setStatus(Schedule::STATUS_ERROR);
298-
throw new \Exception('No callbacks found');
296+
// phpcs:ignore Magento2.Exceptions.DirectThrow
297+
throw new \Exception(sprintf('No callbacks found for cron job %s', $jobCode));
299298
}
300299
$model = $this->_objectManager->create($jobConfig['instance']);
301300
$callback = [$model, $jobConfig['method']];
302301
if (!is_callable($callback)) {
303302
$schedule->setStatus(Schedule::STATUS_ERROR);
303+
// phpcs:ignore Magento2.Exceptions.DirectThrow
304304
throw new \Exception(
305305
sprintf('Invalid callback: %s::%s can\'t be called', $jobConfig['instance'], $jobConfig['method'])
306306
);
@@ -311,15 +311,18 @@ protected function _runJob($scheduledTime, $currentTime, $jobConfig, $schedule,
311311
$this->startProfiling();
312312
try {
313313
$this->logger->info(sprintf('Cron Job %s is run', $jobCode));
314+
//phpcs:ignore Magento2.Functions.DiscouragedFunction
314315
call_user_func_array($callback, [$schedule]);
315316
} catch (\Throwable $e) {
316317
$schedule->setStatus(Schedule::STATUS_ERROR);
317-
$this->logger->error(sprintf(
318-
'Cron Job %s has an error: %s. Statistics: %s',
319-
$jobCode,
320-
$e->getMessage(),
321-
$this->getProfilingStat()
322-
));
318+
$this->logger->error(
319+
sprintf(
320+
'Cron Job %s has an error: %s. Statistics: %s',
321+
$jobCode,
322+
$e->getMessage(),
323+
$this->getProfilingStat()
324+
)
325+
);
323326
if (!$e instanceof \Exception) {
324327
$e = new \RuntimeException(
325328
'Error when running a cron job',
@@ -332,16 +335,22 @@ protected function _runJob($scheduledTime, $currentTime, $jobConfig, $schedule,
332335
$this->stopProfiling();
333336
}
334337

335-
$schedule->setStatus(Schedule::STATUS_SUCCESS)->setFinishedAt(strftime(
336-
'%Y-%m-%d %H:%M:%S',
337-
$this->dateTime->gmtTimestamp()
338-
));
338+
$schedule->setStatus(
339+
Schedule::STATUS_SUCCESS
340+
)->setFinishedAt(
341+
strftime(
342+
'%Y-%m-%d %H:%M:%S',
343+
$this->dateTime->gmtTimestamp()
344+
)
345+
);
339346

340-
$this->logger->info(sprintf(
341-
'Cron Job %s is successfully finished. Statistics: %s',
342-
$jobCode,
343-
$this->getProfilingStat()
344-
));
347+
$this->logger->info(
348+
sprintf(
349+
'Cron Job %s is successfully finished. Statistics: %s',
350+
$jobCode,
351+
$this->getProfilingStat()
352+
)
353+
);
345354
}
346355

347356
/**
@@ -391,6 +400,28 @@ private function getPendingSchedules($groupId)
391400
return $pendingJobs;
392401
}
393402

403+
/**
404+
* Return job collection from database with status 'pending', 'running' or 'success'
405+
*
406+
* @param string $groupId
407+
* @return \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
408+
*/
409+
private function getNonExitedSchedules($groupId)
410+
{
411+
$jobs = $this->_config->getJobs();
412+
$pendingJobs = $this->_scheduleFactory->create()->getCollection();
413+
$pendingJobs->addFieldToFilter(
414+
'status',
415+
[
416+
'in' => [
417+
Schedule::STATUS_PENDING, Schedule::STATUS_RUNNING, Schedule::STATUS_SUCCESS
418+
]
419+
]
420+
);
421+
$pendingJobs->addFieldToFilter('job_code', ['in' => array_keys($jobs[$groupId])]);
422+
return $pendingJobs;
423+
}
424+
394425
/**
395426
* Generate cron schedule
396427
*
@@ -422,7 +453,7 @@ private function generateSchedules($groupId)
422453
null
423454
);
424455

425-
$schedules = $this->getPendingSchedules($groupId);
456+
$schedules = $this->getNonExitedSchedules($groupId);
426457
$exists = [];
427458
/** @var Schedule $schedule */
428459
foreach ($schedules as $schedule) {
@@ -653,11 +684,14 @@ private function cleanupScheduleMismatches()
653684
/** @var \Magento\Cron\Model\ResourceModel\Schedule $scheduleResource */
654685
$scheduleResource = $this->_scheduleFactory->create()->getResource();
655686
foreach ($this->invalid as $jobCode => $scheduledAtList) {
656-
$scheduleResource->getConnection()->delete($scheduleResource->getMainTable(), [
657-
'status = ?' => Schedule::STATUS_PENDING,
658-
'job_code = ?' => $jobCode,
659-
'scheduled_at in (?)' => $scheduledAtList,
660-
]);
687+
$scheduleResource->getConnection()->delete(
688+
$scheduleResource->getMainTable(),
689+
[
690+
'status = ?' => Schedule::STATUS_PENDING,
691+
'job_code = ?' => $jobCode,
692+
'scheduled_at in (?)' => $scheduledAtList,
693+
]
694+
);
661695
}
662696
return $this;
663697
}

app/code/Magento/Cron/Test/Unit/Observer/ProcessCronQueueObserverTest.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,8 @@ public function testDispatchExceptionTooLate()
355355
*/
356356
public function testDispatchExceptionNoCallback()
357357
{
358-
$exceptionMessage = 'No callbacks found';
358+
$jobCode = 'test_job1';
359+
$exceptionMessage = sprintf('No callbacks found for cron job %s', $jobCode);
359360
$exception = new \Exception(__($exceptionMessage));
360361

361362
$dateScheduledAt = date('Y-m-d H:i:s', $this->time - 86400);
@@ -364,7 +365,7 @@ public function testDispatchExceptionNoCallback()
364365
)->setMethods(
365366
['getJobCode', 'tryLockJob', 'getScheduledAt', 'save', 'setStatus', 'setMessages', '__wakeup', 'getStatus']
366367
)->disableOriginalConstructor()->getMock();
367-
$schedule->expects($this->any())->method('getJobCode')->will($this->returnValue('test_job1'));
368+
$schedule->expects($this->any())->method('getJobCode')->will($this->returnValue($jobCode));
368369
$schedule->expects($this->once())->method('getScheduledAt')->will($this->returnValue($dateScheduledAt));
369370
$schedule->expects($this->once())->method('tryLockJob')->will($this->returnValue(true));
370371
$schedule->expects(
@@ -384,7 +385,7 @@ public function testDispatchExceptionNoCallback()
384385

385386
$this->loggerMock->expects($this->once())->method('critical')->with($exception);
386387

387-
$jobConfig = ['test_group' => ['test_job1' => ['instance' => 'Some_Class']]];
388+
$jobConfig = ['test_group' => [$jobCode => ['instance' => 'Some_Class']]];
388389

389390
$this->_config->expects($this->exactly(2))->method('getJobs')->will($this->returnValue($jobConfig));
390391

0 commit comments

Comments
 (0)