Skip to content

Commit

Permalink
ENGCOM-5335: Added function to check against running/pending/successf…
Browse files Browse the repository at this point in the history
…ul cron tasks #23312
  • Loading branch information
sidolov authored Jun 26, 2019
2 parents 7fa4b0d + 18e1e19 commit 3028d55
Showing 1 changed file with 59 additions and 25 deletions.
84 changes: 59 additions & 25 deletions app/code/Magento/Cron/Observer/ProcessCronQueueObserver.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

/**
* Handling cron jobs
*/
namespace Magento\Cron\Observer;

use Magento\Cron\Model\Schedule;
use Magento\Framework\App\State;
use Magento\Framework\Console\Cli;
use Magento\Framework\Event\ObserverInterface;
use Magento\Cron\Model\Schedule;
use Magento\Framework\Profiler\Driver\Standard\Stat;
use Magento\Framework\Profiler\Driver\Standard\StatFactory;

Expand Down Expand Up @@ -204,7 +203,6 @@ public function __construct(
*/
public function execute(\Magento\Framework\Event\Observer $observer)
{

$currentTime = $this->dateTime->gmtTimestamp();
$jobGroupsRoot = $this->_config->getJobs();
// sort jobs groups to start from used in separated process
Expand Down Expand Up @@ -258,7 +256,6 @@ function ($groupId) use ($currentTime, $jobsRoot) {
*/
private function lockGroup($groupId, callable $callback)
{

if (!$this->lockManager->lock(self::LOCK_PREFIX . $groupId, self::LOCK_TIMEOUT)) {
$this->logger->warning(
sprintf(
Expand Down Expand Up @@ -293,17 +290,20 @@ protected function _runJob($scheduledTime, $currentTime, $jobConfig, $schedule,
$scheduleLifetime = $scheduleLifetime * self::SECONDS_IN_MINUTE;
if ($scheduledTime < $currentTime - $scheduleLifetime) {
$schedule->setStatus(Schedule::STATUS_MISSED);
// phpcs:ignore Magento2.Exceptions.DirectThrow
throw new \Exception(sprintf('Cron Job %s is missed at %s', $jobCode, $schedule->getScheduledAt()));
}

if (!isset($jobConfig['instance'], $jobConfig['method'])) {
$schedule->setStatus(Schedule::STATUS_ERROR);
// phpcs:ignore Magento2.Exceptions.DirectThrow
throw new \Exception(sprintf('No callbacks found for cron job %s', $jobCode));
}
$model = $this->_objectManager->create($jobConfig['instance']);
$callback = [$model, $jobConfig['method']];
if (!is_callable($callback)) {
$schedule->setStatus(Schedule::STATUS_ERROR);
// phpcs:ignore Magento2.Exceptions.DirectThrow
throw new \Exception(
sprintf('Invalid callback: %s::%s can\'t be called', $jobConfig['instance'], $jobConfig['method'])
);
Expand All @@ -314,15 +314,18 @@ protected function _runJob($scheduledTime, $currentTime, $jobConfig, $schedule,
$this->startProfiling();
try {
$this->logger->info(sprintf('Cron Job %s is run', $jobCode));
//phpcs:ignore Magento2.Functions.DiscouragedFunction
call_user_func_array($callback, [$schedule]);
} catch (\Throwable $e) {
$schedule->setStatus(Schedule::STATUS_ERROR);
$this->logger->error(sprintf(
'Cron Job %s has an error: %s. Statistics: %s',
$jobCode,
$e->getMessage(),
$this->getProfilingStat()
));
$this->logger->error(
sprintf(
'Cron Job %s has an error: %s. Statistics: %s',
$jobCode,
$e->getMessage(),
$this->getProfilingStat()
)
);
if (!$e instanceof \Exception) {
$e = new \RuntimeException(
'Error when running a cron job',
Expand All @@ -335,16 +338,22 @@ protected function _runJob($scheduledTime, $currentTime, $jobConfig, $schedule,
$this->stopProfiling();
}

$schedule->setStatus(Schedule::STATUS_SUCCESS)->setFinishedAt(strftime(
'%Y-%m-%d %H:%M:%S',
$this->dateTime->gmtTimestamp()
));
$schedule->setStatus(
Schedule::STATUS_SUCCESS
)->setFinishedAt(
strftime(
'%Y-%m-%d %H:%M:%S',
$this->dateTime->gmtTimestamp()
)
);

$this->logger->info(sprintf(
'Cron Job %s is successfully finished. Statistics: %s',
$jobCode,
$this->getProfilingStat()
));
$this->logger->info(
sprintf(
'Cron Job %s is successfully finished. Statistics: %s',
$jobCode,
$this->getProfilingStat()
)
);
}

/**
Expand Down Expand Up @@ -395,6 +404,28 @@ private function getPendingSchedules($groupId)
return $pendingJobs;
}

/**
* Return job collection from database with status 'pending', 'running' or 'success'
*
* @param string $groupId
* @return \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
*/
private function getNonExitedSchedules($groupId)
{
$jobs = $this->_config->getJobs();
$pendingJobs = $this->_scheduleFactory->create()->getCollection();
$pendingJobs->addFieldToFilter(
'status',
[
'in' => [
Schedule::STATUS_PENDING, Schedule::STATUS_RUNNING, Schedule::STATUS_SUCCESS
]
]
);
$pendingJobs->addFieldToFilter('job_code', ['in' => array_keys($jobs[$groupId])]);
return $pendingJobs;
}

/**
* Generate cron schedule
*
Expand Down Expand Up @@ -426,7 +457,7 @@ private function generateSchedules($groupId)
null
);

$schedules = $this->getPendingSchedules($groupId);
$schedules = $this->getNonExitedSchedules($groupId);
$exists = [];
/** @var Schedule $schedule */
foreach ($schedules as $schedule) {
Expand Down Expand Up @@ -669,11 +700,14 @@ private function cleanupScheduleMismatches()
/** @var \Magento\Cron\Model\ResourceModel\Schedule $scheduleResource */
$scheduleResource = $this->_scheduleFactory->create()->getResource();
foreach ($this->invalid as $jobCode => $scheduledAtList) {
$scheduleResource->getConnection()->delete($scheduleResource->getMainTable(), [
'status = ?' => Schedule::STATUS_PENDING,
'job_code = ?' => $jobCode,
'scheduled_at in (?)' => $scheduledAtList,
]);
$scheduleResource->getConnection()->delete(
$scheduleResource->getMainTable(),
[
'status = ?' => Schedule::STATUS_PENDING,
'job_code = ?' => $jobCode,
'scheduled_at in (?)' => $scheduledAtList,
]
);
}
return $this;
}
Expand Down

0 comments on commit 3028d55

Please sign in to comment.