Retry   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 104
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 0
dl 0
loc 104
ccs 42
cts 42
cp 1
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A atLeast() 0 6 1
A forever() 0 6 1
A once() 0 6 1
A twice() 0 6 1
A withDelay() 0 6 1
A onlyOnException() 0 6 1
A abortOnException() 0 6 1
A isInsideRetryLimit() 0 8 4
A isExpectedException() 0 4 2
A isAbortableException() 0 4 2
A canRetry() 0 6 3
A run() 0 16 4
1
<?php declare(strict_types=1);
2
3
namespace Aguimaraes\Bureaucrat;
4
5
class Retry implements PolicyInterface
6
{
7
    private $limit;
8
9
    private $delay = 0;
10
11
    private $on = [];
12
13
    private $abortOn = [];
14
15
    private $retries = 0;
16
17 4
    public function atLeast(int $limit) : Retry
18
    {
19 4
        $this->limit = $limit;
20
21 4
        return $this;
22
    }
23
24 4
    public function forever() : Retry
25
    {
26 4
        $this->limit = 0;
27
28 4
        return $this;
29
    }
30
31 4
    public function once() : Retry
32
    {
33 4
        $this->limit = 1;
34
35 4
        return $this;
36
    }
37
38 2
    public function twice() : Retry
39
    {
40 2
        $this->limit = 2;
41
42 2
        return $this;
43
    }
44
45 2
    public function withDelay(int $delay, int $unit) : Retry
46
    {
47 2
        $this->delay = $delay * $unit;
48
49 2
        return $this;
50
    }
51
52 2
    public function onlyOnException(string $exception) : Retry
53
    {
54 2
        $this->on = array_merge($this->on, [$exception]);
55
56 2
        return $this;
57
    }
58
59 2
    public function abortOnException(string $exception) : Retry
60
    {
61 2
        $this->abortOn = array_merge($this->abortOn, [$exception]);
62
63 2
        return $this;
64
    }
65
66 16
    public function isInsideRetryLimit()
67
    {
68 16
        if (is_null($this->limit) || ($this->limit > 0 && $this->retries >= $this->limit)) {
69 10
            return false;
70
        }
71
72 14
        return true;
73
    }
74
75 14
    public function isExpectedException(\Exception $e)
76
    {
77 14
        return empty($this->on) || in_array(get_class($e), $this->on);
78
    }
79
80 14
    public function isAbortableException(\Exception $e)
81
    {
82 14
        return !empty($this->abortOn) && in_array(get_class($e), $this->abortOn);
83
    }
84
85 14
    public function canRetry(\Exception $e)
86
    {
87 14
        return $this->isExpectedException($e)
88 14
            && $this->isInsideRetryLimit()
89 14
            && !$this->isAbortableException($e);
90
    }
91
92 16
    public function run(callable $operation, $args = [])
93
    {
94
        try {
95 16
            return $operation(...$args);
96 14
        } catch (\Exception $e) {
97 14
            if ($this->canRetry($e)) {
98 14
                if ($this->delay > 0) {
99 2
                    usleep($this->delay);
100
                }
101 14
                $this->retries++;
102
103 14
                return $this->run($operation, $args);
104
            }
105 4
            throw new $e;
106
        }
107
    }
108
}
109