Passed
Pull Request — master (#62)
by
unknown
07:41
created

RetryableJobManager::saveHistory()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4

Importance

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