ConnectionPool::getConnection()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace Dazzle\ChannelZmq\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 string $id
76
     * @return bool
77
     */
78
    public function setConnection($id)
79
    {
80
        if (!$this->existsConnection($id))
81
        {
82
            $this->connectionPool[$id] = $this->register();
83
            $ret = true;
84
        }
85
        else
86
        {
87
            $this->connectionPool[$id] = $this->register($this->connectionPool[$id]);
88
            $ret = false;
89
        }
90
91
        return $ret;
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 mixed[]
112
     */
113
    public function getConnection($id)
114
    {
115
        return $this->connectionPool[$id];
116
    }
117
118
    /**
119
     * @param string $id
120
     * @return bool
121
     */
122
    public function existsConnection($id)
123
    {
124
        return isset($this->connectionPool[$id]);
125
    }
126
127
    /**
128
     * @param string $id
129
     * @return bool
130
     */
131
    public function validateConnection($id)
132
    {
133
        if (!$this->existsConnection($id))
134
        {
135
            return false;
136
        }
137
138
        return $this->validateIn($this->generateConst(), $this->getConnection($id));
139
    }
140
141
    /**
142
     * @return string[]
143
     */
144
    public function removeInvalid()
145
    {
146
        $toDel = [];
147
        $const = $this->generateConst();
148
149
        foreach ($this->connectionPool as $cid=>$cdata)
150
        {
151
            if (!$this->validateIn($const, $cdata))
152
            {
153
                $toDel[] = $cid;
154
            }
155
        }
156
157
        foreach ($toDel as $cid)
158
        {
159
            unset($this->connectionPool[$cid]);
160
        }
161
162
        return $toDel;
163
    }
164
165
    /**
166
     * @param string $id
167
     * @param string $property
168
     * @param mixed $value
169
     */
170
    public function setConnectionProperty($id, $property, $value)
171
    {
172
        if (!$this->existsConnection($id))
173
        {
174
            $this->setConnection($id);
175
        }
176
177
        $this->connectionPool[$id][$property] = $value;
178
    }
179
180
    /**
181
     * @param string $id
182
     * @return bool
183
     */
184
    public function isHeartbeatNeeded($id)
185
    {
186
        if (!$this->existsConnection($id))
187
        {
188
            return true;
189
        }
190
191
        return $this->validateOut($this->generateConst(), $this->getConnection($id));
192
    }
193
194
    /**
195
     * @param $id
196
     * @return bool
197
     */
198
    public function registerHeartbeat($id)
199
    {
200
        if (!$this->existsConnection($id))
201
        {
202
            return false;
203
        }
204
205
        $this->connectionPool[$id]['timestampOut'] = $this->getNow() + $this->heartbeatOffset;
206
207
        return true;
208
    }
209
210
    /**
211
     * @return float
212
     */
213
    public function getNow()
214
    {
215
        $callback = $this->now;
216
        return $callback();
217
    }
218
219
    /**
220
     * @param callable $callback
221
     */
222
    public function setNow(callable $callback)
223
    {
224
        $this->now = $callback;
225
    }
226
227
    /**
228
     *
229
     */
230
    public function resetNow()
231
    {
232
        $this->now = function() {
233
            return round(microtime(true)*1000);
234
        };
235
    }
236
237
    /**
238
     * @param array $current
239
     * @return mixed[]
240
     */
241
    protected function register($current = [])
242
    {
243
        return [
244
            'timestampIn'  => $this->getNow() + $this->keepaliveOffset,
245
            'timestampOut' => isset($current['timestampOut']) ? $current['timestampOut'] : 0
246
        ];
247
    }
248
249
    /**
250
     * @param mixed[] $const
251
     * @param mixed[] $data
252
     * @return bool
253
     */
254
    protected function validateIn($const, $data)
255
    {
256
        return $data['timestampIn'] === 0 || ($const['timestampIn'] - $data['timestampIn']) <= 0;
257
    }
258
259
    /**
260
     * @param mixed[] $const
261
     * @param mixed[] $data
262
     * @return bool
263
     */
264
    protected function validateOut($const, $data)
265
    {
266
        return $data['timestampOut'] === 0 || ($const['timestampOut'] - $data['timestampOut']) > 0;
267
    }
268
269
    /**
270
     * @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...
271
     */
272
    protected function generateConst()
273
    {
274
        $now = $this->getNow();
275
276
        return [
277
            'timestampIn'  => $now,
278
            'timestampOut' => $now
279
        ];
280
    }
281
}
282