1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Cron\Model\ResourceModel;
/**
* Schedule resource
*
* @api
* @since 100.0.2
*/
class Schedule extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
/**
* Initialize resource
*
* @return void
*/
public function _construct()
{
$this->_init('cron_schedule', 'schedule_id');
}
/**
* Sets new schedule status only if it's in the expected current status.
*
* If schedule is currently in $currentStatus, set it to $newStatus and
* return true. Otherwise, return false.
*
* @param string $scheduleId
* @param string $newStatus
* @param string $currentStatus
* @return bool
*/
public function trySetJobStatusAtomic($scheduleId, $newStatus, $currentStatus)
{
$connection = $this->getConnection();
$result = $connection->update(
$this->getTable('cron_schedule'),
['status' => $newStatus],
['schedule_id = ?' => $scheduleId, 'status = ?' => $currentStatus]
);
if ($result == 1) {
return true;
}
return false;
}
/**
* Sets schedule status only if no existing schedules with the same job code
* have that status. This is used to implement locking for cron jobs.
*
* If the schedule is currently in $currentStatus and there are no existing
* schedules with the same job code and $newStatus, set the schedule to
* $newStatus and return true. Otherwise, return false.
*
* @param string $scheduleId
* @param string $newStatus
* @param string $currentStatus
* @return bool
* @since 100.2.0
*/
public function trySetJobUniqueStatusAtomic($scheduleId, $newStatus, $currentStatus)
{
$connection = $this->getConnection();
// this condition added to avoid cron jobs locking after incorrect termination of running job
$match = $connection->quoteInto(
'existing.job_code = current.job_code ' .
'AND (existing.executed_at > UTC_TIMESTAMP() - INTERVAL 1 DAY OR existing.executed_at IS NULL) ' .
'AND existing.status = ?',
$newStatus
);
$selectIfUnlocked = $connection->select()
->joinLeft(
['existing' => $this->getTable('cron_schedule')],
$match,
['status' => new \Zend_Db_Expr($connection->quote($newStatus))]
)
->where('current.schedule_id = ?', $scheduleId)
->where('current.status = ?', $currentStatus)
->where('existing.schedule_id IS NULL');
$update = $connection->updateFromSelect($selectIfUnlocked, ['current' => $this->getTable('cron_schedule')]);
$result = $connection->query($update)->rowCount();
if ($result == 1) {
return true;
}
return false;
}
}