Skip to content

Commit 6450e44

Browse files
committed
ACP2E-2427: [TMNA] Many Indexer Log Events per Second
1 parent 7f58418 commit 6450e44

File tree

2 files changed

+91
-15
lines changed

2 files changed

+91
-15
lines changed

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

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -337,17 +337,11 @@ private function lockGroup(string $groupId, callable $callback): void
337337
*
338338
* @return void
339339
* @throws Exception|Throwable
340+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
340341
*/
341342
protected function _runJob($scheduledTime, $currentTime, $jobConfig, $schedule, $groupId)
342343
{
343344
$jobCode = $schedule->getJobCode();
344-
$scheduleLifetime = $this->getCronGroupConfigurationValue($groupId, self::XML_PATH_SCHEDULE_LIFETIME);
345-
$scheduleLifetime = $scheduleLifetime * self::SECONDS_IN_MINUTE;
346-
if ($scheduledTime < $currentTime - $scheduleLifetime) {
347-
$schedule->setStatus(Schedule::STATUS_MISSED);
348-
// phpcs:ignore Magento2.Exceptions.DirectThrow
349-
throw new Exception(sprintf('Cron Job %s is missed at %s', $jobCode, $schedule->getScheduledAt()));
350-
}
351345

352346
if (!isset($jobConfig['instance'], $jobConfig['method'])) {
353347
$schedule->setStatus(Schedule::STATUS_ERROR);
@@ -863,7 +857,7 @@ private function processPendingJobs(string $groupId, array $jobsRoot, int $curre
863857
}
864858

865859
$scheduledTime = strtotime($schedule->getScheduledAt());
866-
if ($scheduledTime > $currentTime) {
860+
if (!$this->shouldRunJob($schedule, $groupId, $currentTime, (int) $scheduledTime)) {
867861
continue;
868862
}
869863

@@ -980,4 +974,62 @@ private function setProcessTitle(string $jobCode, string $groupId): void
980974
cli_set_process_title($this->originalProcessTitle . " # group: $groupId, job: $jobCode");
981975
}
982976
}
977+
978+
/**
979+
* Mark job as missed
980+
*
981+
* @param Schedule $schedule
982+
* @return void
983+
*/
984+
private function markJobAsMissed(Schedule $schedule): void
985+
{
986+
$jobCode = $schedule->getJobCode();
987+
$scheduleId = $schedule->getId();
988+
$resource = $schedule->getResource();
989+
$connection = $resource->getConnection();
990+
$message = sprintf('Cron Job %s is missed at %s', $jobCode, $schedule->getScheduledAt());
991+
$result = $this->retrier->execute(
992+
function () use ($resource, $connection, $scheduleId, $message) {
993+
return $connection->update(
994+
$resource->getTable('cron_schedule'),
995+
['status' => Schedule::STATUS_MISSED, 'messages' => $message],
996+
['schedule_id = ?' => $scheduleId, 'status = ?' => Schedule::STATUS_PENDING]
997+
);
998+
},
999+
$connection
1000+
);
1001+
if ($result == 1) {
1002+
$schedule->setStatus(Schedule::STATUS_MISSED);
1003+
$schedule->setMessages($message);
1004+
if ($this->state->getMode() === State::MODE_DEVELOPER) {
1005+
$this->logger->info($message);
1006+
}
1007+
}
1008+
}
1009+
1010+
/**
1011+
* Check if job should be run
1012+
*
1013+
* @param Schedule $schedule
1014+
* @param string $groupId
1015+
* @param int $currentTime
1016+
* @param int $scheduledTime
1017+
* @return bool
1018+
*/
1019+
private function shouldRunJob(Schedule $schedule, string $groupId, int $currentTime, int $scheduledTime): bool
1020+
{
1021+
if ($scheduledTime > $currentTime) {
1022+
return false;
1023+
}
1024+
1025+
$scheduleLifetime = $this->getCronGroupConfigurationValue($groupId, self::XML_PATH_SCHEDULE_LIFETIME);
1026+
$scheduleLifetime = $scheduleLifetime * self::SECONDS_IN_MINUTE;
1027+
1028+
if ($scheduledTime < $currentTime - $scheduleLifetime) {
1029+
$this->markJobAsMissed($schedule);
1030+
return false;
1031+
}
1032+
1033+
return true;
1034+
}
9831035
}

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

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
use Magento\Framework\DB\Adapter\AdapterInterface;
2828
use Magento\Framework\Event\ManagerInterface;
2929
use Magento\Framework\Event\Observer;
30+
use Magento\Framework\Exception\LocalizedException;
3031
use Magento\Framework\Lock\LockManagerInterface;
3132
use Magento\Framework\Model\AbstractModel;
3233
use Magento\Framework\Process\PhpExecutableFinderFactory;
@@ -304,7 +305,17 @@ public function testDispatchCanNotLock(): void
304305
$this->eventManager->expects($this->never())->method('dispatch');
305306
$this->cacheMock->expects($this->any())->method('load')->willReturn($lastRun);
306307
$this->scopeConfigMock->expects($this->any())
307-
->method('getValue')->willReturn(0);
308+
->method('getValue')
309+
->willReturnMap(
310+
[
311+
[
312+
'system/cron/test_group/schedule_lifetime',
313+
ScopeInterface::SCOPE_STORE,
314+
null,
315+
2 * 24 * 60
316+
],
317+
]
318+
);
308319
$this->consoleRequestMock->expects($this->any())
309320
->method('getParam')->willReturn('test_group');
310321

@@ -366,6 +377,7 @@ public function testDispatchExceptionTooLate(): void
366377
{
367378
$exceptionMessage = 'Cron Job test_job1 is missed at 2017-07-30 15:00:00';
368379
$jobCode = 'test_job1';
380+
$scheduleId = 2;
369381

370382
$lastRun = $this->time + 10000000;
371383
$this->eventManager->expects($this->never())->method('dispatch');
@@ -375,7 +387,7 @@ public function testDispatchExceptionTooLate(): void
375387

376388
$dateScheduledAt = date('Y-m-d H:i:s', $this->time - 86400);
377389
$schedule = $this->getMockBuilder(Schedule::class)
378-
->onlyMethods(['tryLockJob', 'save', '__wakeup', 'getResource'])
390+
->onlyMethods(['tryLockJob', 'save', '__wakeup', 'getResource', 'getId'])
379391
->addMethods(
380392
[
381393
'getJobCode',
@@ -388,9 +400,10 @@ public function testDispatchExceptionTooLate(): void
388400
]
389401
)->disableOriginalConstructor()
390402
->getMock();
403+
$schedule->expects($this->atLeastOnce())->method('getId')->willReturn($scheduleId);
391404
$schedule->expects($this->atLeastOnce())->method('getJobCode')->willReturn($jobCode);
392405
$schedule->expects($this->atLeastOnce())->method('getScheduledAt')->willReturn($dateScheduledAt);
393-
$schedule->expects($this->once())->method('tryLockJob')->willReturn(true);
406+
$schedule->expects($this->never())->method('tryLockJob')->willReturn(true);
394407
$schedule->expects(
395408
$this->any()
396409
)->method(
@@ -399,9 +412,7 @@ public function testDispatchExceptionTooLate(): void
399412
Schedule::STATUS_MISSED
400413
)->willReturnSelf();
401414
$schedule->expects($this->once())->method('setMessages')->with($exceptionMessage);
402-
$schedule->expects($this->atLeastOnce())->method('getStatus')->willReturn(Schedule::STATUS_MISSED);
403-
$schedule->expects($this->atLeastOnce())->method('getMessages')->willReturn($exceptionMessage);
404-
$schedule->expects($this->once())->method('save');
415+
$schedule->expects($this->never())->method('save');
405416
$schedule->expects($this->once())->method('getResource')->willReturn($this->scheduleResourceMock);
406417

407418
$connectionMock = $this->getMockForAbstractClass(AdapterInterface::class);
@@ -410,11 +421,24 @@ public function testDispatchExceptionTooLate(): void
410421
->method('getConnection')
411422
->willReturn($connectionMock);
412423

424+
$this->scheduleResourceMock->expects($this->once())
425+
->method('getTable')
426+
->willReturnArgument(0);
427+
428+
$connectionMock->expects($this->once())
429+
->method('update')
430+
->with(
431+
'cron_schedule',
432+
['status' => Schedule::STATUS_MISSED, 'messages' => $exceptionMessage],
433+
['schedule_id = ?' => $scheduleId, 'status = ?' => Schedule::STATUS_PENDING]
434+
);
435+
413436
$this->retrierMock->expects($this->once())
414437
->method('execute')
415438
->willReturnCallback(
416439
function ($callback) {
417-
return $callback();
440+
$callback();
441+
return '1';
418442
}
419443
);
420444

0 commit comments

Comments
 (0)