Passed
Push — master ( a3c72d...4f79df )
by Leonardo
08:02 queued 14s
created

RedisClusterAdapter::setOpenCircuit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 4
c 1
b 0
f 0
dl 0
loc 6
rs 10
cc 1
nc 1
nop 2
1
<?php declare(strict_types=1);
2
3
namespace LeoCarmo\CircuitBreaker\Adapters;
4
5
class RedisClusterAdapter implements AdapterInterface
6
{
7
    /**
8
     * @var \Redis
9
     */
10
    protected $redis;
11
12
    /**
13
     * @var string
14
     */
15
    protected string $redisNamespace;
16
17
    /**
18
     * Set settings for start circuit service
19
     *
20
     * @param $redis
21
     * @param string $redisNamespace
22
     */
23
    public function __construct($redis, string $redisNamespace)
24
    {
25
        $this->checkExtensionLoaded();
26
        $this->redis = $redis;
27
        $this->redisNamespace = $redisNamespace;
28
    }
29
30
    protected function checkExtensionLoaded(): void
31
    {
32
        if (! extension_loaded('redis')) {
33
            throw new \RuntimeException('Extension redis is required to use RedisAdapter.');
34
        }
35
    }
36
37
    /**
38
     * @param string $service
39
     * @return bool
40
     */
41
    public function isOpen(string $service): bool
42
    {
43
        return (bool) $this->redis->get(
44
            $this->makeNamespace($service) . ':open'
45
        );
46
    }
47
48
    /**
49
     * @param string $service
50
     * @param int $failureRateThreshold
51
     * @return bool
52
     */
53
    public function reachRateLimit(string $service, int $failureRateThreshold): bool
54
    {
55
        $failures = (int) $this->redis->get(
56
            $this->makeNamespace($service) . ':failures'
57
        );
58
59
        return ($failures >= $failureRateThreshold);
60
    }
61
62
    /**
63
     * @param string $service
64
     * @return bool
65
     */
66
    public function isHalfOpen(string $service): bool
67
    {
68
        return (bool) $this->redis->get(
69
            $this->makeNamespace($service) . ':half_open'
70
        );
71
    }
72
73
    /**
74
     * @param string $service
75
     * @param int $timeWindow
76
     * @return bool
77
     */
78
    public function incrementFailure(string $service, int $timeWindow): bool
79
    {
80
        $serviceName = $this->makeNamespace($service) . ':failures';
81
82
        if (! $this->redis->get($serviceName)) {
83
            $this->redis->incr($serviceName);
84
            return (bool) $this->redis->expire($serviceName, $timeWindow);
85
        }
86
87
        return (bool) $this->redis->incr($serviceName);
88
    }
89
90
    /**
91
     * @param string $service
92
     */
93
    public function setSuccess(string $service): void
94
    {
95
        $serviceName = $this->makeNamespace($service);
96
97
        $this->redis->del($serviceName . ':open');
98
        $this->redis->del($serviceName . ':failures');
99
        $this->redis->del($serviceName . ':half_open');
100
    }
101
102
    /**
103
     * @param string $service
104
     * @param int $timeWindow
105
     */
106
    public function setOpenCircuit(string $service, int $timeWindow): void
107
    {
108
        $this->redis->set(
109
            $this->makeNamespace($service) . ':open',
110
            time(),
111
            $timeWindow
112
        );
113
    }
114
115
    /**
116
     * @param string $service
117
     * @param int $timeWindow
118
     * @param int $intervalToHalfOpen
119
     */
120
    public function setHalfOpenCircuit(string $service, int $timeWindow, int $intervalToHalfOpen): void
121
    {
122
        $this->redis->set(
123
            $this->makeNamespace($service) . ':half_open',
124
            time(),
125
            ($timeWindow + $intervalToHalfOpen)
126
        );
127
    }
128
129
    public function getFailuresCounter(string $service): int
130
    {
131
        $failures = $this->redis->get(
132
            $this->makeNamespace($service) . ':failures'
133
        );
134
135
        return (int) $failures;
136
    }
137
138
    /**
139
     * @param string $service
140
     * @return string
141
     */
142
    protected function makeNamespace(string $service): string
143
    {
144
        return 'circuit-breaker:' . $this->redisNamespace . ':' . $service;
145
    }
146
}
147