CircuitBreaker   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 91
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 91
rs 10
c 0
b 0
f 0
wmc 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A addConfigurations() 0 4 2
A isAvailable() 0 6 2
A reportFailure() 0 6 1
A __construct() 0 4 1
A getConfig() 0 7 2
A reportSuccess() 0 10 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace NiR\CircuitBreaker;
6
7
use NiR\CircuitBreaker\Exception\ServiceNotDefined;
8
use NiR\CircuitBreaker\Exception\StorageFailure;
9
use NiR\CircuitBreaker\Service\Configuration;
10
11
/**
12
 * Circuit breaker mechanism.
13
 *
14
 * @author Albin Kerouanton <[email protected]>
15
 */
16
final class CircuitBreaker
17
{
18
    /** @var Storage */
19
    private $storage;
20
21
    /** @var Service\Configuration[] */
22
    private $configs;
23
24
    /**
25
     * @param Storage         $storage
26
     * @param Configuration[] ...$configurations Configuration of the services this CB supports.
27
     */
28
    public function __construct(Storage $storage, Configuration ...$configurations)
29
    {
30
        $this->storage = $storage;
31
        $this->addConfigurations(...$configurations);
32
    }
33
34
    /**
35
     * Add service configurations to be used by this CB.
36
     *
37
     * @param Configuration[] ...$configurations
38
     */
39
    public function addConfigurations(Configuration ...$configurations)
40
    {
41
        foreach ($configurations as $configuration) {
42
            $this->configs[$configuration->getServiceName()] = $configuration;
43
        }
44
    }
45
46
    /**
47
     * Is service available and could be used?
48
     *
49
     * @param string $service Name of the service.
50
     *
51
     * @throws ServiceNotDefined If the service is not registered.
52
     * @throws StorageFailure
53
     *
54
     * @return bool
55
     */
56
    public function isAvailable(string $service): bool
57
    {
58
        $config = $this->getConfig($service);
59
        $status = $this->storage->loadStatus($config);
60
61
        return $status->isClose() || $status->isHalfOpen();
62
    }
63
64
    /**
65
     * Report a successful interaction with a service.
66
     *
67
     * @param string $service Name of the service.
68
     *
69
     * @throws ServiceNotDefined If the service is not registered.
70
     * @throws StorageFailure
71
     */
72
    public function reportSuccess(string $service)
73
    {
74
        $config = $this->getConfig($service);
75
        $status = $this->storage->loadStatus($config);
76
77
        if ($status->isClose() === true) {
78
            return;
79
        }
80
81
        $this->storage->saveStatus($config, $status->close());
82
    }
83
84
    /**
85
     * Report a failed interaction with a service.
86
     *
87
     * @param string $service Name of the service.
88
     *
89
     * @throws ServiceNotDefined If the service is not registered.
90
     * @throws StorageFailure
91
     */
92
    public function reportFailure(string $service)
93
    {
94
        $config = $this->getConfig($service);
95
        $status = $this->storage->loadStatus($config);
96
97
        $this->storage->saveStatus($config, $status->failed());
98
    }
99
100
    private function getConfig(string $service): Configuration
101
    {
102
        if (!isset($this->configs[$service])) {
103
            throw ServiceNotDefined::named($service);
104
        }
105
106
        return $this->configs[$service];
107
    }
108
}
109