Passed
Push — master ( 84cbf2...ef661a )
by Leonardo
04:29 queued 02:41
created

RedisAdapter::reachRateLimit()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 7
rs 10
1
<?php
2
3
namespace LeoCarmo\CircuitBreaker\Adapters;
4
5
use LeoCarmo\CircuitBreaker\CircuitBreaker;
6
7
class RedisAdapter implements AdapterInterface
8
{
9
10
    /**
11
     * @var \Redis
12
     */
13
    protected $redis;
14
15
    /**
16
     * @var string
17
     */
18
    protected $redisNamespace;
19
20
    /**
21
     * @var array
22
     */
23
    protected $cachedService = [];
24
25
    /**
26
     * Set settings for start circuit service
27
     *
28
     * @param \Redis $redis
29
     * @param string $redisNamespace
30
     */
31
    public function __construct(\Redis $redis, string $redisNamespace)
32
    {
33
        $this->redis = $redis;
34
        $this->redisNamespace = $redisNamespace;
35
    }
36
37
    /**
38
     * @param string $service
39
     * @return bool|string
40
     */
41
    public function isOpen(string $service) : bool
42
    {
43
        return $this->redis->get($this->makeNamespace($service) . ':open');
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->redis->get...ce($service) . ':open') returns the type string which is incompatible with the type-hinted return boolean.
Loading history...
44
    }
45
46
    /**
47
     * @param string $service
48
     * @return bool
49
     */
50
    public function reachRateLimit(string $service) : bool
51
    {
52
        $failures = $this->redis->get(
53
            $this->makeNamespace($service) . ':failures'
54
        );
55
56
        return $failures && $failures >= CircuitBreaker::getServiceSetting($service, 'failureRateThreshold');
57
    }
58
59
    /**
60
     * @param string $service
61
     * @return bool|string
62
     */
63
    public function isHalfOpen(string $service) : bool
64
    {
65
        return (bool) $this->redis->get($this->makeNamespace($service) . ':half_open');
66
    }
67
68
    /**
69
     * @param string $service
70
     * @return bool
71
     */
72
    public function incrementFailure(string $service) : bool
73
    {
74
        $serviceFailures = self::makeNamespace($service) . ':failures';
0 ignored issues
show
Bug Best Practice introduced by
The method LeoCarmo\CircuitBreaker\...dapter::makeNamespace() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

74
        $serviceFailures = self::/** @scrutinizer ignore-call */ makeNamespace($service) . ':failures';
Loading history...
75
76
        if (! $this->redis->get($serviceFailures)) {
77
            $this->redis->multi();
78
            $this->redis->incr($serviceFailures);
79
            $this->redis->expire($serviceFailures, CircuitBreaker::getServiceSetting($service, 'timeWindow'));
80
            return (bool) $this->redis->exec()[0] ?? false;
81
        }
82
83
        return (bool) $this->redis->incr($serviceFailures);
84
    }
85
86
    /**
87
     * @param string $service
88
     * @return bool
89
     */
90
    public function setSuccess(string $service) : bool
91
    {
92
        return (bool) $this->redis->delete(
93
            $this->redis->keys(
94
                $this->makeNamespace($service) . ':*'
95
            )
96
        );
97
    }
98
99
    /**
100
     * @param string $service
101
     */
102
    public function setOpenCircuit(string $service) : void
103
    {
104
        $this->redis->set(
105
            $this->makeNamespace($service) . ':open',
106
            time(),
107
            CircuitBreaker::getServiceSetting($service, 'timeWindow')
108
        );
109
    }
110
111
    /**
112
     * @param string $service
113
     */
114
    public function setHalfOpenCircuit(string $service) : void
115
    {
116
        $this->redis->set(
117
            $this->makeNamespace($service) . ':half_open',
118
            time(),
119
            CircuitBreaker::getServiceSetting($service, 'timeWindow')
120
            + CircuitBreaker::getServiceSetting($service, 'intervalToHalfOpen')
121
        );
122
    }
123
124
    /**
125
     * @param string $service
126
     * @return string
127
     */
128
    protected function makeNamespace(string $service)
129
    {
130
        if (isset($this->cachedService[$service])) {
131
            return $this->cachedService[$service];
132
        }
133
134
        return $this->cachedService[$service] = 'circuit-breaker:' . $this->redisNamespace . ':' . base64_encode($service);
135
    }
136
}
137