RetryableJobManager::recordTiming()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 4
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 3
rs 10
1
<?php
2
3
namespace Dtc\QueueBundle\Manager;
4
5
use Dtc\QueueBundle\Model\BaseJob;
6
use Dtc\QueueBundle\Model\Job;
7
use Dtc\QueueBundle\Model\JobTiming;
8
use Dtc\QueueBundle\Model\RetryableJob;
9
use Dtc\QueueBundle\Util\Util;
10
11
abstract class RetryableJobManager extends AbstractJobManager
12
{
13
    protected $defaultMaxRetries;
14
    protected $defaultMaxFailures;
15
    protected $defaultMaxExceptions;
16
17
    protected $autoRetryOnFailure;
18
    protected $autoRetryOnException;
19
20 11
    public static function getAllStatuses()
21
    {
22 11
        $statuses = parent::getAllStatuses();
23 11
        $statuses[RetryableJob::STATUS_MAX_RETRIES] = 0;
24 11
        $statuses[RetryableJob::STATUS_MAX_FAILURES] = 0;
25 11
        $statuses[RetryableJob::STATUS_MAX_EXCEPTIONS] = 0;
26
27 11
        return $statuses;
28
    }
29
30
    abstract protected function retryableSave(RetryableJob $job);
31
32
    /**
33
     * @param bool $retry bool
34
     *
35
     * @return
36
     */
37
    abstract protected function retryableSaveHistory(RetryableJob $job, $retry);
38
39 93
    public function save(Job $job)
40
    {
41 93
        if (!$job instanceof RetryableJob) {
42 4
            throw new \InvalidArgumentException('Job is not instanceof '.RetryableJob::class);
43
        }
44
45 93
        if (!$job->getId()) {
46 93
            $this->setBaseRetryableJobDefaults($job);
47
        }
48 93
        $this->recordTiming($job);
49 93
        $job->setUpdatedAt(Util::getMicrotimeDateTime());
50
51 93
        return $this->retryableSave($job);
52
    }
53
54
    /**
55
     * @return bool true if retry
56
     */
57 34
    public function saveHistory(Job $job)
58
    {
59 34
        if (!$job instanceof RetryableJob) {
60 4
            throw new \InvalidArgumentException('job not instance of '.RetryableJob::class);
61
        }
62
63 34
        switch ($job->getStatus()) {
64 34
            case BaseJob::STATUS_FAILURE:
65 11
                return $this->retryableSaveHistory($job, $this->updateJobFailure($job));
66 23
            case BaseJob::STATUS_EXCEPTION:
67 8
                return $this->retryableSaveHistory($job, $this->updateJobException($job));
68
        }
69
70 15
        return $this->retryableSaveHistory($job, false);
71
    }
72
73 8
    private function updateJobException(RetryableJob $job)
74
    {
75 8
        return $this->updateJobMax($job, 'Exceptions', RetryableJob::STATUS_MAX_EXCEPTIONS, $this->autoRetryOnException);
76
    }
77
78
    /**
79
     * @param string $type
80
     * @param bool   $autoRetry
81
     */
82 21
    protected function updateJobMax(RetryableJob $job, $type, $maxStatus, $autoRetry)
83
    {
84 21
        $setMethod = 'set'.$type;
85 21
        $getMethod = 'get'.$type;
86 21
        $getMax = 'getMax'.$type;
87 21
        $job->$setMethod(intval($job->$getMethod()) + 1);
88 21
        if (!$this->updateMaxStatus($job, $maxStatus, $job->$getMax(), $job->$getMethod()) &&
89 21
            !$this->updateMaxStatus($job, RetryableJob::STATUS_MAX_RETRIES, $job->getMaxRetries(), $job->getRetries())) {
90 20
            if ($autoRetry) {
91 18
                return $this->resetRetryableJob($job);
92
            }
93
        }
94
95 21
        return false;
96
    }
97
98 11
    private function updateJobFailure(RetryableJob $job)
99
    {
100 11
        return $this->updateJobMax($job, 'Failures', RetryableJob::STATUS_MAX_FAILURES, $this->autoRetryOnFailure);
101
    }
102
103
    /**
104
     * Determine if we've hit a max retry condition.
105
     *
106
     * @param string   $status
107
     * @param int|null $max
108
     * @param int      $count
109
     *
110
     * @return bool
111
     */
112 23
    protected function updateMaxStatus(RetryableJob $job, $status, $max = null, $count = 0)
113
    {
114 23
        if (null !== $max && $count >= $max) {
115 21
            $job->setStatus($status);
116
117 21
            return true;
118
        }
119
120 22
        return false;
121
    }
122
123 18
    protected function resetRetryableJob(RetryableJob $job)
124
    {
125 18
        if ($this->resetJob($job)) {
126 18
            $this->getJobTimingManager()->recordTiming(JobTiming::STATUS_INSERT);
127
128 18
            return true;
129
        }
130
131
        return false;
132
    }
133
134
    /**
135
     * @return bool true if the job was successfully "reset", i.e. re-queued
136
     */
137
    abstract protected function resetJob(RetryableJob $job);
138
139 93
    protected function setBaseRetryableJobDefaults(RetryableJob $job)
140
    {
141 93
        if (null === $job->getMaxExceptions()) {
0 ignored issues
show
introduced by
The condition null === $job->getMaxExceptions() is always false.
Loading history...
142 43
            $job->setMaxExceptions($this->defaultMaxExceptions);
143
        }
144
145 93
        if (null === $job->getMaxRetries()) {
0 ignored issues
show
introduced by
The condition null === $job->getMaxRetries() is always false.
Loading history...
146 43
            $job->setMaxRetries($this->defaultMaxRetries);
147
        }
148
149 93
        if (null === $job->getMaxFailures()) {
0 ignored issues
show
introduced by
The condition null === $job->getMaxFailures() is always false.
Loading history...
150 43
            $job->setMaxFailures($this->defaultMaxFailures);
151
        }
152
153 93
        if (null === $job->getCrcHash()) {
0 ignored issues
show
introduced by
The condition null === $job->getCrcHash() is always false.
Loading history...
154 93
            $hashValues = [get_class($job), $job->getMethod(), $job->getWorkerName(), $job->getArgs()];
155 93
            $crcHash = hash('sha256', serialize($hashValues));
156 93
            $job->setCrcHash($crcHash);
157
        }
158 93
    }
159
160
    /**
161
     * @return int|null
162
     */
163 8
    public function getDefaultMaxRetries()
164
    {
165 8
        return $this->defaultMaxRetries;
166
    }
167
168
    /**
169
     * @param int|null $defaultMaxRetries
170
     */
171 8
    public function setDefaultMaxRetries($defaultMaxRetries)
172
    {
173 8
        $this->defaultMaxRetries = $defaultMaxRetries;
174 8
    }
175
176
    /**
177
     * @return int|null
178
     */
179 8
    public function getDefaultMaxFailures()
180
    {
181 8
        return $this->defaultMaxFailures;
182
    }
183
184
    /**
185
     * @param int|null $defaultMaxFailures
186
     */
187 8
    public function setDefaultMaxFailures($defaultMaxFailures)
188
    {
189 8
        $this->defaultMaxFailures = $defaultMaxFailures;
190 8
    }
191
192
    /**
193
     * @return bool
194
     */
195 8
    public function getAutoRetryOnFailure()
196
    {
197 8
        return $this->autoRetryOnFailure;
198
    }
199
200
    /**
201
     * @param bool $autoRetryOnFailure
202
     */
203 24
    public function setAutoRetryOnFailure($autoRetryOnFailure)
204
    {
205 24
        $this->autoRetryOnFailure = $autoRetryOnFailure;
206 24
    }
207
208
    /**
209
     * @return bool
210
     */
211 8
    public function getAutoRetryOnException()
212
    {
213 8
        return $this->autoRetryOnException;
214
    }
215
216
    /**
217
     * @param bool $autoRetryOnException
218
     */
219 16
    public function setAutoRetryOnException($autoRetryOnException)
220
    {
221 16
        $this->autoRetryOnException = $autoRetryOnException;
222 16
    }
223
224
    /**
225
     * @return int|null
226
     */
227 8
    public function getDefaultMaxExceptions()
228
    {
229 8
        return $this->defaultMaxExceptions;
230
    }
231
232
    /**
233
     * @param int|null $defaultMaxExceptions
234
     */
235 8
    public function setDefaultMaxExceptions($defaultMaxExceptions)
236
    {
237 8
        $this->defaultMaxExceptions = $defaultMaxExceptions;
238 8
    }
239
240 93
    protected function recordTiming(Job $job)
241
    {
242 93
        $status = JobTiming::STATUS_INSERT;
243 93
        if ($job->getWhenAt() && $job->getWhenAt() > Util::getMicrotimeDateTime()) {
244 5
            $status = JobTiming::STATUS_INSERT_DELAYED;
245
        }
246
247 93
        $this->getJobTimingManager()->recordTiming($status);
248 93
    }
249
}
250