Passed
Pull Request — master (#10)
by Leonardo
06:36
created

SwooleTableAdapter   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 146
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 16
eloc 50
c 1
b 0
f 1
dl 0
loc 146
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A reachRateLimit() 0 16 3
A isHalfOpen() 0 11 2
A setOpenCircuit() 0 12 1
A setHalfOpenCircuit() 0 14 1
A __construct() 0 4 1
A createTable() 0 7 1
A checkExtensionLoaded() 0 4 2
A setSuccess() 0 5 1
A incrementFailure() 0 13 2
A isOpen() 0 11 2
1
<?php declare(strict_types=1);
2
3
namespace LeoCarmo\CircuitBreaker\Adapters;
4
5
use Swoole\Table;
6
7
class SwooleTableAdapter implements AdapterInterface
8
{
9
    protected Table $table;
10
11
    public function __construct()
12
    {
13
        $this->checkExtensionLoaded();
14
        $this->table = $this->createTable();
15
    }
16
17
    protected function createTable()
18
    {
19
        $table = new Table(12);
20
        $table->column('count', Table::TYPE_INT, 4);
21
        $table->column('until_date', Table::TYPE_FLOAT);
22
        $table->create();
23
        return $table;
24
    }
25
26
    protected function checkExtensionLoaded()
27
    {
28
        if (! extension_loaded('swoole')) {
29
            throw new \RuntimeException('Extension swoole is required to use SwooleTableAdapter.');
30
        }
31
    }
32
33
    /**
34
     * @param string $service
35
     * @param int $timeWindow
36
     * @return bool
37
     */
38
    public function incrementFailure(string $service, int $timeWindow): bool
39
    {
40
        $key = "{$service}-failures";
41
42
        if ($this->table->exist($key)) {
43
            return is_integer($this->table->incr($key, 'count'));
44
        }
45
46
        $date = (new \DateTime("+{$timeWindow} seconds"));
47
48
        return $this->table->set($key, [
49
            'count' => 1,
50
            'until_date' => $date->getTimestamp(),
51
        ]);
52
    }
53
54
    public function reachRateLimit(string $service, int $failureRateThreshold): bool
55
    {
56
        $key = "{$service}-failures";
57
58
        if (! $this->table->exist($key)) {
59
            return false;
60
        }
61
62
        $failures = $this->table->get($key);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $failures is correct as $this->table->get($key) targeting Swoole\Table::get() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
63
64
        if (microtime(true) > $failures['until_date']) {
65
            $this->table->delete("{$service}-failures");
66
            return false;
67
        }
68
69
        return ($failures['count'] >= $failureRateThreshold);
70
    }
71
72
    /**
73
     * @param string $service
74
     */
75
    public function setSuccess(string $service): void
76
    {
77
        $this->table->delete("{$service}-failures");
78
        $this->table->delete("{$service}-open");
79
        $this->table->delete("{$service}-half_open");
80
    }
81
82
    /**
83
     * @param string $service
84
     * @return bool
85
     */
86
    public function isOpen(string $service): bool
87
    {
88
        $key = "{$service}-open";
89
90
        if (! $this->table->exists($key)) {
91
            return false;
92
        }
93
94
        $open = $this->table->get($key, 'until_date');
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $open is correct as $this->table->get($key, 'until_date') targeting Swoole\Table::get() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
95
96
        return (microtime(true) < $open);
97
    }
98
99
    /**
100
     * @param string $service
101
     * @return bool|string
102
     */
103
    public function isHalfOpen(string $service): bool
104
    {
105
        $key = "{$service}-half_open";
106
107
        if (! $this->table->exists($key)) {
108
            return false;
109
        }
110
111
        $halfOpen = $this->table->get($key, 'until_date');
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $halfOpen is correct as $this->table->get($key, 'until_date') targeting Swoole\Table::get() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
112
113
        return (microtime(true) < $halfOpen);
114
    }
115
116
    /**
117
     * @param string $service
118
     * @param int $timeWindow
119
     */
120
    public function setOpenCircuit(string $service, int $timeWindow): void
121
    {
122
        $date = (new \DateTime("+{$timeWindow} seconds"));
123
124
        $this->table->set(
125
            "{$service}-open",
126
            [
127
                'until_date' => $date->getTimestamp(),
128
            ]
129
        );
130
131
        $this->table->delete("{$service}-failures");
132
    }
133
134
    /**
135
     * @param string $service
136
     * @param int $timeWindow
137
     * @param int $intervalToHalfOpen
138
     */
139
    public function setHalfOpenCircuit(string $service, int $timeWindow, int $intervalToHalfOpen): void
140
    {
141
        $seconds = ($timeWindow + $intervalToHalfOpen);
142
143
        $date = (new \DateTime("+{$seconds} seconds"));
144
145
        $this->table->set(
146
            "{$service}-half_open",
147
            [
148
                'until_date' => $date->getTimestamp(),
149
            ]
150
        );
151
152
        $this->table->delete("{$service}-failures");
153
    }
154
}
155