Completed
Pull Request — master (#37)
by Eugene
08:41
created

Client::flushSpaces()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
ccs 0
cts 0
cp 0
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Tarantool Client package.
7
 *
8
 * (c) Eugene Leonovich <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Tarantool\Client;
15
16
use Tarantool\Client\Connection\StreamConnection;
17
use Tarantool\Client\Exception\RequestFailed;
18
use Tarantool\Client\Handler\DefaultHandler;
19
use Tarantool\Client\Handler\Handler;
20
use Tarantool\Client\Handler\MiddlewareHandler;
21
use Tarantool\Client\Middleware\AuthMiddleware;
22
use Tarantool\Client\Middleware\Middleware;
23
use Tarantool\Client\Middleware\RetryMiddleware;
24
use Tarantool\Client\Packer\PurePacker;
25
use Tarantool\Client\Request\Call;
26
use Tarantool\Client\Request\Evaluate;
27
use Tarantool\Client\Request\Execute;
28
use Tarantool\Client\Request\Ping;
29 55
use Tarantool\Client\Schema\Index;
30
use Tarantool\Client\Schema\Space;
31 55
32 55
final class Client
33 55
{
34
    private $handler;
35 3
    private $spaces = [];
36
37 3
    public function __construct(Handler $handler)
38
    {
39
        $this->handler = $handler;
40 2
    }
41
42 2
    public static function fromDefaults() : self
43
    {
44
        return new self(new DefaultHandler(
45 54
            StreamConnection::createTcp(),
46
            new PurePacker()
47 54
        ));
48
    }
49 33
50 2
    public static function fromOptions(array $options) : self
51
    {
52 33
        $connectionOptions = [];
53
        if (isset($options['connect_timeout'])) {
54 51
            $connectionOptions['connect_timeout'] = $options['connect_timeout'];
55
        }
56 51
        if (isset($options['socket_timeout'])) {
57 51
            $connectionOptions['socket_timeout'] = $options['socket_timeout'];
58 51
        }
59
        if (isset($options['tcp_nodelay'])) {
60 14
            $connectionOptions['tcp_nodelay'] = $options['tcp_nodelay'];
61
        }
62 14
63
        $connection = StreamConnection::create($options['uri'] ?? StreamConnection::DEFAULT_URI, $connectionOptions);
64
        $handler = new DefaultHandler($connection, new PurePacker());
65 14
66
        if (isset($options['username'])) {
67 14
            $handler = new MiddlewareHandler(
68 12
                new AuthMiddleware($options['username'], $options['password'] ?? ''),
69
                $handler
70
            );
71 14
        }
72 14
        if (isset($options['max_retries']) && 0 !== $options['max_retries']) {
73
            $handler = new MiddlewareHandler(
74 10
                RetryMiddleware::linear($options['max_retries']),
75 10
                $handler
76
            );
77 10
        }
78
79 10
        return new self($handler);
80
    }
81
82 10
    public static function fromDsn(string $dsn) : self
83
    {
84 10
        $dsn = Dsn::parse($dsn);
85
86 10
        $connectionOptions = [];
87
        if (null !== $timeout = $dsn->getInt('connect_timeout')) {
88
            $connectionOptions['connect_timeout'] = $timeout;
89
        }
90
        if (null !== $timeout = $dsn->getInt('socket_timeout')) {
91
            $connectionOptions['socket_timeout'] = $timeout;
92
        }
93
        if (null !== $tcpNoDelay = $dsn->getBool('socket_timeout')) {
94 64
            $connectionOptions['tcp_nodelay'] = $tcpNoDelay;
95
        }
96 64
97 58
        $connection = $dsn->isTcp()
98
            ? StreamConnection::createTcp($dsn->getConnectionUri(), $connectionOptions)
99
            : StreamConnection::createUds($dsn->getConnectionUri(), $connectionOptions);
100 16
101 10
        $handler = new DefaultHandler($connection, new PurePacker());
102
103
        if ($username = $dsn->getUsername()) {
104 14
            $handler = new MiddlewareHandler(
105
                new AuthMiddleware($username, $dsn->getPassword() ?? ''),
106 12
                $handler
107
            );
108
        }
109 8
        if ($maxRetries = $dsn->getInt('max_retries')) {
110
            $handler = new MiddlewareHandler(
111 8
                RetryMiddleware::linear($maxRetries),
112
                $handler
113 8
            );
114
        }
115
116 26
        return new self($handler);
117
    }
118 26
119
    public function withMiddleware(Middleware $middleware, Middleware ...$middlewares) : self
120 26
    {
121
        $new = clone $this;
122
        $new->handler = new MiddlewareHandler($middleware, $this->handler);
123 12
124
        if ($middlewares) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $middlewares of type array<integer,Tarantool\...\Middleware\Middleware> is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
125 12
            $new->handler = MiddlewareHandler::create($new->handler, $middlewares);
126 12
        }
127
128 115
        return $new;
129
    }
130 115
131 30
    public function getHandler() : Handler
132
    {
133
        return $this->handler;
134 113
    }
135 113
136
    public function ping() : void
137 109
    {
138
        $this->handler->handle(new Ping());
139
    }
140 14
141
    public function getSpace(string $spaceName) : Space
142 14
    {
143 14
        if (isset($this->spaces[$spaceName])) {
144 14
            return $this->spaces[$spaceName];
145
        }
146 14
147 3
        $spaceId = $this->getSpaceIdByName($spaceName);
148
149
        return $this->spaces[$spaceName] = $this->spaces[$spaceId] = new Space($this->handler, $spaceId);
150 12
    }
151
152
    public function getSpaceById(int $spaceId) : Space
153
    {
154
        if (isset($this->spaces[$spaceId])) {
155
            return $this->spaces[$spaceId];
156
        }
157
158
        return $this->spaces[$spaceId] = new Space($this->handler, $spaceId);
159
    }
160
161
    public function call(string $funcName, ...$args) : array
162
    {
163
        $request = new Call($funcName, $args);
164
165
        return $this->handler->handle($request)->getBodyField(IProto::DATA);
166
    }
167
168
    public function executeQuery(string $sql, ...$params) : SqlQueryResult
169
    {
170
        $request = new Execute($sql, $params);
171
        $response = $this->handler->handle($request);
172
173
        return new SqlQueryResult(
174
            $response->getBodyField(IProto::DATA),
175
            $response->getBodyField(IProto::METADATA)
176
        );
177
    }
178
179
    public function executeUpdate(string $sql, ...$params) : SqlUpdateResult
180
    {
181
        $request = new Execute($sql, $params);
182
183
        return new SqlUpdateResult(
184
            $this->handler->handle($request)->getBodyField(IProto::SQL_INFO)
185
        );
186
    }
187
188
    public function evaluate(string $expr, ...$args) : array
189
    {
190
        $request = new Evaluate($expr, $args);
191
192
        return $this->handler->handle($request)->getBodyField(IProto::DATA);
193
    }
194
195
    public function flushSpaces() : void
196
    {
197
        $this->spaces = [];
198
    }
199
200
    private function getSpaceIdByName(string $spaceName) : int
201
    {
202
        $schema = $this->getSpaceById(Space::VSPACE_ID);
203
        $data = $schema->select([$spaceName], Index::SPACE_NAME);
204
205
        if ([] === $data) {
206
            throw RequestFailed::unknownSpace($spaceName);
207
        }
208
209
        return $data[0][0];
210
    }
211
}
212