Pool   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 157
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 45
dl 0
loc 157
rs 10
c 0
b 0
f 0
wmc 17

9 Methods

Rating   Name   Duplication   Size   Complexity  
A stats() 0 3 1
A __construct() 0 28 3
A closed() 0 3 1
A release() 0 3 1
A shutdown() 0 7 1
A resource() 0 3 1
A recycle() 0 3 1
A select() 0 13 4
A stopping() 0 10 4
1
<?php
2
/**
3
 * Conn pool
4
 * User: moyo
5
 * Date: 09/08/2017
6
 * Time: 3:05 PM
7
 */
8
9
namespace Carno\Pool;
10
11
use function Carno\Coroutine\race;
12
use function Carno\Coroutine\timeout;
13
use Carno\Pool\Contracts\Select;
14
use Carno\Pool\Exception\SelectUnavailableException;
15
use Carno\Pool\Exception\ShutdownTimeoutException;
16
use Carno\Pool\Features\Heartbeat;
17
use Carno\Pool\Features\IdleRecycling;
18
use Carno\Promise\Promise;
19
use Carno\Promise\Promised;
20
use Closure;
21
22
class Pool
23
{
24
    /**
25
     * @var string
26
     */
27
    protected $identify = null;
28
29
    /**
30
     * @var Connections
31
     */
32
    protected $connections = null;
33
34
    /**
35
     * @var IdleRecycling
36
     */
37
    protected $recycling = null;
38
39
    /**
40
     * @var Heartbeat
41
     */
42
    protected $heartbeat = null;
43
44
    /**
45
     * @var bool
46
     */
47
    protected $stopped = false;
48
49
    /**
50
     * @var Promised
51
     */
52
    protected $closed = null;
53
54
    /**
55
     * @var Stats
56
     */
57
    private $stats = null;
58
59
    /**
60
     * Pool constructor.
61
     * @param Options $options
62
     * @param Closure $dialer
63
     * @param string $identify
64
     */
65
    public function __construct(Options $options, Closure $dialer, string $identify = 'conn')
66
    {
67
        $this->connections = new Connections(
68
            $this,
69
            $options,
70
            new Connector($this, $dialer, $this->identify = $identify)
71
        );
72
73
        if ($options->icInterval > 0) {
74
            $this->connections->setIRecycling(
75
                $this->recycling = new IdleRecycling($options, $this->connections)
76
            );
77
        }
78
79
        if ($options->hbInterval > 0) {
80
            $this->heartbeat = new Heartbeat($options, $this->connections);
81
        }
82
83
        $this->closed()->then(function () {
84
            $this->stopping();
85
            $this->stats->untrack();
86
            $this->connections->cleanup();
87
            Observer::closed($this);
88
        });
89
90
        $this->stats = new Stats($this->connections);
91
92
        Observer::created($this);
93
    }
94
95
    /**
96
     * @return string
97
     */
98
    public function resource() : string
99
    {
100
        return $this->identify;
101
    }
102
103
    /**
104
     * @return Stats
105
     */
106
    public function stats() : Stats
107
    {
108
        return $this->stats;
109
    }
110
111
    /**
112
     * @param int $mode
113
     * @return Poolable
114
     */
115
    public function select(int $mode = Select::IDLING)
116
    {
117
        if ($this->stopped) {
118
            throw new SelectUnavailableException('This pool has been stopped');
119
        }
120
121
        switch ($mode) {
122
            case Select::IDLING:
123
                return $this->connections->getIdled();
124
            case Select::RANDOM:
0 ignored issues
show
introduced by
The constant Carno\Pool\Contracts\Select::RANDOM has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

124
            case /** @scrutinizer ignore-deprecated */ Select::RANDOM:
Loading history...
125
                return $this->connections->getLived();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->connections->getLived() also could return the type Carno\Promise\Promised which is incompatible with the documented return type Carno\Pool\Poolable.
Loading history...
Deprecated Code introduced by
The function Carno\Pool\Connections::getLived() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

125
                return /** @scrutinizer ignore-deprecated */ $this->connections->getLived();
Loading history...
126
            default:
127
                return null;
128
        }
129
    }
130
131
    /**
132
     * @param Poolable $conn
133
     */
134
    public function recycle(Poolable $conn) : void
135
    {
136
        $this->connections->putIdled($conn);
137
    }
138
139
    /**
140
     * @param Poolable $conn
141
     */
142
    public function release(Poolable $conn) : void
143
    {
144
        $this->connections->released($conn);
145
    }
146
147
    /**
148
     * @return Promised
149
     */
150
    public function shutdown() : Promised
151
    {
152
        $this->stopping();
153
154
        $this->connections->exit(true, 'pool-shutdown');
155
156
        return race($this->closed(), timeout(45000, ShutdownTimeoutException::class, $this->identify));
157
    }
158
159
    /**
160
     */
161
    public function stopping() : void
162
    {
163
        if ($this->stopped) {
164
            return;
165
        }
166
167
        $this->heartbeat && $this->heartbeat->shutdown();
168
        $this->recycling && $this->recycling->shutdown();
169
170
        $this->stopped = true;
171
    }
172
173
    /**
174
     * @return Promised
175
     */
176
    public function closed() : Promised
177
    {
178
        return $this->closed ?? $this->closed = Promise::deferred();
179
    }
180
}
181