CircuitBreaker::getAdapter()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 1
c 2
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 0
1
<?php declare(strict_types=1);
2
3
namespace LeoCarmo\CircuitBreaker;
4
5
use LeoCarmo\CircuitBreaker\Adapters\AdapterInterface;
6
7
class CircuitBreaker
8
{
9
    public const TIME_WINDOW = 60;
10
    public const FAILURE_RATE_THRESHOLD = 50;
11
    public const INTERVAL_TO_HALF_OPEN = 30;
12
13
    /**
14
     * @var AdapterInterface
15
     */
16
    protected AdapterInterface $adapter;
17
18
    /**
19
     * @var string
20
     */
21
    protected string $service;
22
23
    /**
24
     * @var array
25
     */
26
    protected array $settings = [];
27
28
    /**
29
     * @var array
30
     */
31
    protected array $defaultSettings = [
32
        'timeWindow' => self::TIME_WINDOW,
33
        'failureRateThreshold' => self::FAILURE_RATE_THRESHOLD,
34
        'intervalToHalfOpen' => self::INTERVAL_TO_HALF_OPEN,
35
    ];
36
37
    /**
38
     * @param AdapterInterface $adapter
39
     * @param string $service
40
     */
41
    public function __construct(AdapterInterface $adapter, string $service)
42
    {
43
        $this->adapter = $adapter;
44
        $this->service = $service;
45
    }
46
47
    /**
48
     * @return AdapterInterface
49
     */
50
    public function getAdapter(): AdapterInterface
51
    {
52
        return $this->adapter;
53
    }
54
55
    /**
56
     * @return string
57
     */
58
    public function getService(): string
59
    {
60
        return $this->service;
61
    }
62
63
    /**
64
     * Set global settings for all services
65
     *
66
     * @param array $settings
67
     * @return void
68
     */
69
    public function setSettings(array $settings): void
70
    {
71
        foreach ($this->defaultSettings as $defaultSettingKey => $defaultSettingValue) {
72
            $this->settings[$defaultSettingKey] = (int) ($settings[$defaultSettingKey] ?? $defaultSettingValue);
73
        }
74
    }
75
76
    /**
77
     * @return array
78
     */
79
    public function getSettings(): array
80
    {
81
        return $this->settings;
82
    }
83
84
    /**
85
     * @param string $name
86
     * @return mixed
87
     */
88
    public function getSetting(string $name)
89
    {
90
        return $this->settings[$name] ?? $this->defaultSettings[$name];
91
    }
92
93
    /**
94
     * Check if circuit is available (closed)
95
     *
96
     * @return bool
97
     */
98
    public function isAvailable(): bool
99
    {
100
        if ($this->adapter->isOpen($this->service)) {
101
            return false;
102
        }
103
104
        $reachRateLimit = $this->adapter->reachRateLimit(
105
            $this->service,
106
            $this->getSetting('failureRateThreshold')
107
        );
108
109
        if ($reachRateLimit) {
110
            $this->openCircuit();
111
            return false;
112
        }
113
114
        return true;
115
    }
116
117
    /**
118
     * Set new failure for a service
119
     *
120
     * @return void
121
     */
122
    public function failure(): void
123
    {
124
        $isHalfOpen = $this->adapter->isHalfOpen($this->service);
125
126
        if ($isHalfOpen) {
127
            $this->openCircuit();
128
            return;
129
        }
130
131
        $this->adapter->incrementFailure(
132
            $this->service,
133
            $this->getSetting('timeWindow')
134
        );
135
    }
136
137
    /**
138
     * Record success and clear all status
139
     *
140
     * @return void
141
     */
142
    public function success(): void
143
    {
144
        $this->adapter->setSuccess($this->service);
145
    }
146
147
    /**
148
     * Open circuit
149
     */
150
    public function openCircuit(): void
151
    {
152
        $this->adapter->setOpenCircuit(
153
            $this->service,
154
            $this->getSetting('timeWindow')
155
        );
156
        $this->adapter->setHalfOpenCircuit(
157
            $this->service,
158
            $this->getSetting('timeWindow'),
159
            $this->getSetting('intervalToHalfOpen')
160
        );
161
    }
162
163
    public function getFailuresCounter(): int
164
    {
165
        return $this->adapter->getFailuresCounter($this->service);
166
    }
167
}
168