ConnectionPool   A
last analyzed

Complexity

Total Complexity 34

Size/Duplication

Total Lines 284
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 34
lcom 1
cbo 1
dl 0
loc 284
rs 9.2
c 0
b 0
f 0

21 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A __destruct() 0 5 1
A erase() 0 4 1
A getConnected() 0 12 2
A setConnection() 0 15 2
A removeConnection() 0 10 2
A getConnection() 0 4 1
A getData() 0 4 1
A existsConnection() 0 4 1
A validateConnection() 0 9 2
A removeInvalid() 0 20 4
A setConnectionProperty() 0 9 2
A isHeartbeatNeeded() 0 9 2
A registerHeartbeat() 0 11 2
A getNow() 0 5 1
A setNow() 0 4 1
A resetNow() 0 6 1
A register() 0 8 2
A validateIn() 0 4 2
A validateOut() 0 4 2
A generateValidationConst() 0 9 1
1
<?php
2
3
namespace Dazzle\ChannelSocket\Connection;
4
5
/**
6
 * @codeCoverageIgnore
7
 */
8
class ConnectionPool
9
{
10
    /**
11
     * @var callable
12
     */
13
    protected $now;
14
15
    /**
16
     * @var mixed[]
17
     */
18
    protected $connectionPool;
19
20
    /**
21
     * @var float
22
     */
23
    protected $keepaliveOffset;
24
25
    /**
26
     * @var float
27
     */
28
    protected $heartbeatOffset;
29
30
    /**
31
     * @param float $offset
32
     */
33
    public function __construct($offset = 3600000.0, $heartbeat = 200.0)
34
    {
35
        $this->connectionPool = [];
36
        $this->keepaliveOffset = $offset;
37
        $this->heartbeatOffset = $heartbeat;
38
        $this->resetNow();
39
    }
40
41
    /**
42
     *
43
     */
44
    public function __destruct()
45
    {
46
        $this->connectionPool = [];
47
        unset($this->now);
48
    }
49
50
    /**
51
     *
52
     */
53
    public function erase()
54
    {
55
        $this->connectionPool = [];
56
    }
57
58
    /**
59
     * @return string[]
60
     */
61
    public function getConnected()
62
    {
63
        $conns = [];
64
65
        // there is no need for timestamp validation since messages to inactive clients are lost either way
66
        foreach ($this->connectionPool as $connID=>$conn)
67
        {
68
            $conns[] = $connID;
69
        }
70
71
        return $conns;
72
    }
73
74
    /**
75
     * @param Connection $conn
76
     * @return bool
77
     */
78
    public function setConnection(Connection $conn)
79
    {
80
        $id = $conn->id;
81
82
        if ($this->existsConnection($id))
83
        {
84
            $this->connectionPool[$id] = $this->register($conn, $this->connectionPool[$id]);
85
            return false;
86
        }
87
        else
88
        {
89
            $this->connectionPool[$id] = $this->register($conn);
90
            return true;
91
        }
92
    }
93
94
    /**
95
     * @param string $id
96
     * @return bool
97
     */
98
    public function removeConnection($id)
99
    {
100
        if ($this->existsConnection($id))
101
        {
102
            unset($this->connectionPool[$id]);
103
            return true;
104
        }
105
106
        return false;
107
    }
108
109
    /**
110
     * @param string $id
111
     * @return Connection
112
     */
113
    public function getConnection($id)
114
    {
115
        return $this->connectionPool[$id]['conn'];
116
    }
117
118
    /**
119
     * @param string $id
120
     * @return mixed[]
121
     */
122
    public function getData($id)
123
    {
124
        return $this->connectionPool[$id];
125
    }
126
127
    /**
128
     * @param string $id
129
     * @return bool
130
     */
131
    public function existsConnection($id)
132
    {
133
        return isset($this->connectionPool[$id]);
134
    }
135
136
    /**
137
     * @param string $id
138
     * @return bool
139
     */
140
    public function validateConnection($id)
141
    {
142
        if (!$this->existsConnection($id))
143
        {
144
            return false;
145
        }
146
147
        return $this->validateIn($this->generateValidationConst(), $this->getData($id));
148
    }
149
150
    /**
151
     * @return string[]
152
     */
153
    public function removeInvalid()
154
    {
155
        $toDel = [];
156
        $const = $this->generateValidationConst();
157
158
        foreach ($this->connectionPool as $cid=>$cdata)
159
        {
160
            if (!$this->validateIn($const, $cdata))
161
            {
162
                $toDel[] = $cid;
163
            }
164
        }
165
166
        foreach ($toDel as $cid)
167
        {
168
            unset($this->connectionPool[$cid]);
169
        }
170
171
        return $toDel;
172
    }
173
174
    /**
175
     * @param string $id
176
     * @param string $property
177
     * @param mixed $value
178
     */
179
    public function setConnectionProperty($id, $property, $value)
180
    {
181
        if (!$this->existsConnection($id))
182
        {
183
            $this->setConnection($id);
0 ignored issues
show
Documentation introduced by
$id is of type string, but the function expects a object<Dazzle\ChannelSoc...\Connection\Connection>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
184
        }
185
186
        $this->connectionPool[$id][$property] = $value;
187
    }
188
189
    /**
190
     * @param string $id
191
     * @return bool
192
     */
193
    public function isHeartbeatNeeded($id)
194
    {
195
        if (!$this->existsConnection($id))
196
        {
197
            return true;
198
        }
199
200
        return $this->validateOut($this->generateValidationConst(), $this->getData($id));
201
    }
202
203
    /**
204
     * @param $id
205
     * @return bool
206
     */
207
    public function registerHeartbeat($id)
208
    {
209
        if (!$this->existsConnection($id))
210
        {
211
            return false;
212
        }
213
214
        $this->connectionPool[$id]['timestampOut'] = $this->getNow() + $this->heartbeatOffset;
215
216
        return true;
217
    }
218
219
    /**
220
     * @return float
221
     */
222
    public function getNow()
223
    {
224
        $callback = $this->now;
225
        return $callback();
226
    }
227
228
    /**
229
     * @param callable $callback
230
     */
231
    public function setNow(callable $callback)
232
    {
233
        $this->now = $callback;
234
    }
235
236
    /**
237
     *
238
     */
239
    public function resetNow()
240
    {
241
        $this->now = function() {
242
            return round(microtime(true)*1000);
243
        };
244
    }
245
246
    /**
247
     * @param array $current
248
     * @return mixed[]
249
     */
250
    protected function register(Connection $conn, $current = [])
251
    {
252
        return [
253
            'conn'         => $conn,
254
            'timestampIn'  => $this->getNow() + $this->keepaliveOffset,
255
            'timestampOut' => isset($current['timestampOut']) ? $current['timestampOut'] : 0
256
        ];
257
    }
258
259
    /**
260
     * @param mixed[] $const
261
     * @param mixed[] $data
262
     * @return bool
263
     */
264
    protected function validateIn($const, $data)
265
    {
266
        return $data['timestampIn'] === 0 || ($const['timestampIn'] - $data['timestampIn']) <= 0;
267
    }
268
269
    /**
270
     * @param mixed[] $const
271
     * @param mixed[] $data
272
     * @return bool
273
     */
274
    protected function validateOut($const, $data)
275
    {
276
        return $data['timestampOut'] === 0 || ($const['timestampOut'] - $data['timestampOut']) > 0;
277
    }
278
279
    /**
280
     * @return mixed[]
0 ignored issues
show
Documentation introduced by
Should the return type not be array<string,double>?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
281
     */
282
    protected function generateValidationConst()
283
    {
284
        $now = $this->getNow();
285
286
        return [
287
            'timestampIn'  => $now,
288
            'timestampOut' => $now
289
        ];
290
    }
291
}
292