Ganesha::subscribe()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
namespace Ackintosh;
3
4
use Ackintosh\Ganesha\Exception\StorageException;
5
use Ackintosh\Ganesha\StrategyInterface;
6
7
class Ganesha
8
{
9
    /**
10
     * @var string
11
     */
12
    const EVENT_TRIPPED = 'tripped';
13
14
    /**
15
     * @var string
16
     */
17
    const EVENT_CALMED_DOWN = 'calmed_down';
18
19
    /**
20
     * @var string
21
     */
22
    const EVENT_STORAGE_ERROR = 'storage_error';
23
24
    /**
25
     * the status between failure count 0 and trip.
26
     * @var int
27
     */
28
    const STATUS_CALMED_DOWN = 1;
29
30
    /**
31
     * the status between trip and calm down.
32
     * @var int
33
     */
34
    const STATUS_TRIPPED  = 2;
35
36
    /**
37
     * @var StrategyInterface
38
     */
39
    private $strategy;
40
41
    /**
42
     * @var callable[]
43
     */
44
    private $subscribers = [];
45
46
    /**
47
     * @var bool
48
     */
49
    private static $disabled = false;
50
51
    /**
52
     * Ganesha constructor.
53
     *
54
     * @param StrategyInterface $strategy
55
     */
56
    public function __construct($strategy)
57
    {
58
        $this->strategy = $strategy;
59
    }
60
61
    /**
62
     * records failure
63
     *
64
     * @param string $service
65
     * @return void
66
     */
67
    public function failure($service): void
68
    {
69
        try {
70
            if ($this->strategy->recordFailure($service) === self::STATUS_TRIPPED) {
71
                $this->notify(self::EVENT_TRIPPED, $service, '');
72
            }
73
        } catch (StorageException $e) {
74
            $this->notify(self::EVENT_STORAGE_ERROR, $service, 'failed to record failure : ' . $e->getMessage());
75
        }
76
    }
77
78
    /**
79
     * records success
80
     *
81
     * @param string $service
82
     * @return void
83
     */
84
    public function success($service): void
85
    {
86
        try {
87
            if ($this->strategy->recordSuccess($service) === self::STATUS_CALMED_DOWN) {
88
                $this->notify(self::EVENT_CALMED_DOWN, $service, '');
89
            }
90
        } catch (StorageException $e) {
91
            $this->notify(self::EVENT_STORAGE_ERROR, $service, 'failed to record success : ' . $e->getMessage());
92
        }
93
    }
94
95
    /**
96
     * @param string $service
97
     * @return bool
98
     */
99
    public function isAvailable($service): bool
100
    {
101
        if (self::$disabled) {
102
            return true;
103
        }
104
105
        try {
106
            return $this->strategy->isAvailable($service);
107
        } catch (StorageException $e) {
108
            $this->notify(self::EVENT_STORAGE_ERROR, $service, 'failed to isAvailable : ' . $e->getMessage());
109
            // fail-silent
110
            return true;
111
        }
112
    }
113
114
    /**
115
     * @param callable $callable
116
     * @return void
117
     */
118
    public function subscribe(callable $callable): void
119
    {
120
        $this->subscribers[] = $callable;
121
    }
122
123
    /**
124
     * @param string $event
125
     * @param string $service
126
     * @param string $message
127
     * @return void
128
     */
129
    private function notify(string $event, string $service, string $message): void
130
    {
131
        foreach ($this->subscribers as $s) {
132
            call_user_func_array($s, [$event, $service, $message]);
133
        }
134
    }
135
136
    /**
137
     * disable
138
     *
139
     * @return void
140
     */
141
    public static function disable(): void
142
    {
143
        self::$disabled = true;
144
    }
145
146
    /**
147
     * enable
148
     *
149
     * @return void
150
     */
151
    public static function enable(): void
152
    {
153
        self::$disabled = false;
154
    }
155
156
    /**
157
     * resets all counts
158
     *
159
     * @return void
160
     */
161
    public function reset(): void
162
    {
163
        $this->strategy->reset();
164
    }
165
}
166