Skip to content

Commit 2bbb26a

Browse files
author
Oleksandr Iegorov
committed
MAGETWO-84646: Cron jobs incorrect behavior when running job terminated
1 parent 88420db commit 2bbb26a

File tree

2 files changed

+32
-4
lines changed

2 files changed

+32
-4
lines changed

app/code/Magento/Cron/Model/ResourceModel/Schedule.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,14 @@ public function trySetJobUniqueStatusAtomic($scheduleId, $newStatus, $currentSta
6666
{
6767
$connection = $this->getConnection();
6868

69-
$match = $connection->quoteInto('existing.job_code = current.job_code AND existing.status = ?', $newStatus);
69+
// this condition added to avoid cron jobs locking after incorrect termination of running job
70+
$match = $connection->quoteInto(
71+
'existing.job_code = current.job_code ' .
72+
'AND (existing.executed_at > UTC_TIMESTAMP() - INTERVAL 1 DAY OR existing.executed_at IS NULL) ' .
73+
'AND existing.status = ?',
74+
$newStatus
75+
);
76+
7077
$selectIfUnlocked = $connection->select()
7178
->joinLeft(
7279
['existing' => $this->getTable('cron_schedule')],
@@ -75,8 +82,7 @@ public function trySetJobUniqueStatusAtomic($scheduleId, $newStatus, $currentSta
7582
)
7683
->where('current.schedule_id = ?', $scheduleId)
7784
->where('current.status = ?', $currentStatus)
78-
->where('existing.schedule_id IS NULL')
79-
->where('existing.executed_at IS NULL');
85+
->where('existing.schedule_id IS NULL');
8086

8187
$update = $connection->updateFromSelect($selectIfUnlocked, ['current' => $this->getTable('cron_schedule')]);
8288
$result = $connection->query($update)->rowCount();

dev/tests/integration/testsuite/Magento/Cron/Model/ScheduleTest.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,27 @@ public function testTryLockJobAlreadyLockedFails()
5454
$this->assertFalse($schedule->tryLockJob());
5555
}
5656

57+
/**
58+
* If the job is already locked but lock time less than 1 day ago, attempting to lock it again should fail
59+
*/
60+
public function testTryLockJobAlreadyLockedSucceeds()
61+
{
62+
$offsetInThePast = 2*24*60*60;
63+
64+
$oldSchedule = $this->scheduleFactory->create()
65+
->setCronExpr("* * * * *")
66+
->setJobCode("test_job")
67+
->setStatus(Schedule::STATUS_RUNNING)
68+
->setCreatedAt(strftime('%Y-%m-%d %H:%M:%S', $this->dateTime->gmtTimestamp() - $offsetInThePast))
69+
->setScheduledAt(strftime('%Y-%m-%d %H:%M', $this->dateTime->gmtTimestamp() - $offsetInThePast + 60))
70+
->setExecutedAt(strftime('%Y-%m-%d %H:%M', $this->dateTime->gmtTimestamp() - $offsetInThePast + 61));
71+
$oldSchedule->save();
72+
73+
$schedule = $this->createSchedule("test_job", Schedule::STATUS_PENDING);
74+
75+
$this->assertTrue($schedule->tryLockJob());
76+
}
77+
5778
/**
5879
* If there's a job already locked, should not be able to lock another job
5980
*/
@@ -82,9 +103,10 @@ public function testTryLockJobDifferentJobLocked()
82103
* @param string $jobCode
83104
* @param string $status
84105
* @param int $timeOffset
106+
* @param int $executionTimeOffset
85107
* @return Schedule
86108
*/
87-
private function createSchedule($jobCode, $status, $timeOffset = 0)
109+
private function createSchedule($jobCode, $status, $timeOffset = 0, $executionTimeOffset = 0)
88110
{
89111
$schedule = $this->scheduleFactory->create()
90112
->setCronExpr("* * * * *")

0 commit comments

Comments
 (0)