13
13
14
14
namespace Laudis \Neo4j \Bolt ;
15
15
16
- use BadMethodCallException ;
17
16
use Bolt \error \IgnoredException ;
18
17
use Bolt \error \MessageException ;
19
18
use Bolt \protocol \V3 ;
20
19
use Bolt \protocol \V4 ;
21
- use Laudis \ Neo4j \ BoltFactory ;
20
+ use function in_array ;
22
21
use Laudis \Neo4j \Common \ConnectionConfiguration ;
22
+ use Laudis \Neo4j \Contracts \AuthenticateInterface ;
23
23
use Laudis \Neo4j \Contracts \ConnectionInterface ;
24
+ use Laudis \Neo4j \Contracts \FormatterInterface ;
24
25
use Laudis \Neo4j \Databags \BookmarkHolder ;
25
26
use Laudis \Neo4j \Databags \DatabaseInfo ;
26
- use Laudis \Neo4j \Databags \DriverConfiguration ;
27
27
use Laudis \Neo4j \Enum \AccessMode ;
28
28
use Laudis \Neo4j \Enum \ConnectionProtocol ;
29
29
use Laudis \Neo4j \Types \CypherList ;
30
- use LogicException ;
31
30
use Psr \Http \Message \UriInterface ;
32
- use RuntimeException ;
33
31
use function str_starts_with ;
34
32
use WeakReference ;
35
33
36
34
/**
37
- * @implements ConnectionInterface<V3 >
35
+ * @implements ConnectionInterface<array{0: V3, 1: Connection} >
38
36
*
39
- * @psalm-import-type BoltMeta from \Laudis\Neo4j\Contracts\ FormatterInterface
37
+ * @psalm-import-type BoltMeta from FormatterInterface
40
38
*/
41
- final class BoltConnection implements ConnectionInterface
39
+ class BoltConnection implements ConnectionInterface
42
40
{
43
- private ? V3 $ boltProtocol ;
41
+ private V3 $ boltProtocol ;
44
42
/** @psalm-readonly */
45
43
private ConnectionConfiguration $ config ;
46
- /** @psalm-readonly */
47
- private BoltFactory $ factory ;
44
+ private string $ serverState ;
48
45
49
- private string $ serverState = 'DISCONNECTED ' ;
50
46
/**
51
47
* @note We are using references to "subscribed results" to maintain backwards compatibility and try and strike
52
48
* a balance between performance and ease of use.
@@ -61,30 +57,31 @@ final class BoltConnection implements ConnectionInterface
61
57
* @var list<WeakReference<CypherList>>
62
58
*/
63
59
private array $ subscribedResults = [];
60
+ private AuthenticateInterface $ auth ;
61
+ private Connection $ connection ;
62
+ private string $ userAgent ;
64
63
65
- /**
66
- * @psalm-mutation-free
67
- */
68
- public function __construct (BoltFactory $ factory , ?V3 $ boltProtocol , ConnectionConfiguration $ config )
64
+ public function getImplementation ()
69
65
{
70
- $ this ->factory = $ factory ;
71
- $ this ->boltProtocol = $ boltProtocol ;
72
- $ this ->config = $ config ;
73
- if ($ boltProtocol ) {
74
- $ this ->serverState = 'READY ' ;
75
- }
66
+ return [$ this ->boltProtocol , $ this ->connection ];
76
67
}
77
68
78
69
/**
79
70
* @psalm-mutation-free
80
71
*/
81
- public function getImplementation (): V3
72
+ public function __construct ( V3 $ protocol , Connection $ connection , AuthenticateInterface $ auth , string $ userAgent , ConnectionConfiguration $ config )
82
73
{
83
- if ($ this ->boltProtocol === null ) {
84
- throw new RuntimeException ('Connection is closed ' );
85
- }
74
+ $ this ->boltProtocol = $ protocol ;
75
+ $ this ->serverState = 'READY ' ;
76
+ $ this ->auth = $ auth ;
77
+ $ this ->connection = $ connection ;
78
+ $ this ->userAgent = $ userAgent ;
79
+ $ this ->config = $ config ;
80
+ }
86
81
87
- return $ this ->boltProtocol ;
82
+ public function getEncryptionLevel (): string
83
+ {
84
+ return $ this ->connection ->getEncryptionLevel ();
88
85
}
89
86
90
87
/**
@@ -135,6 +132,11 @@ public function getDatabaseInfo(): ?DatabaseInfo
135
132
return $ this ->config ->getDatabaseInfo ();
136
133
}
137
134
135
+ public function getAuthentication (): AuthenticateInterface
136
+ {
137
+ return $ this ->auth ;
138
+ }
139
+
138
140
/**
139
141
* @psalm-mutation-free
140
142
*/
@@ -143,37 +145,12 @@ public function isOpen(): bool
143
145
return $ this ->serverState !== 'DISCONNECTED ' && $ this ->serverState !== 'DEFUNCT ' ;
144
146
}
145
147
146
- public function open (): void
147
- {
148
- if ($ this ->boltProtocol !== null ) {
149
- throw new BadMethodCallException ('Cannot open a connection that is already open ' );
150
- }
151
-
152
- $ this ->boltProtocol = $ this ->factory ->build ()[0 ];
153
- }
154
-
155
148
public function setTimeout (float $ timeout ): void
156
149
{
157
- $ this ->factory -> getConnection () ->setTimeout ($ timeout );
150
+ $ this ->connection ->setTimeout ($ timeout );
158
151
}
159
152
160
- /**
161
- * Closes the connection.
162
- *
163
- * Any of the preconditioned states are: 'READY', 'STREAMING', 'TX_READY', 'TX_STREAMING', 'FAILED', 'INTERRUPTED'.
164
- * Sends signal: 'DISCONNECT'
165
- */
166
- public function close (): void
167
- {
168
- $ this ->consumeResults ();
169
-
170
- $ this ->protocol ()->goodbye ();
171
-
172
- $ this ->serverState = 'DEFUNCT ' ;
173
- $ this ->boltProtocol = null ; // has to be set to null as the sockets don't recover nicely contrary to what the underlying code might lead you to believe
174
- }
175
-
176
- private function consumeResults (): void
153
+ public function consumeResults (): void
177
154
{
178
155
foreach ($ this ->subscribedResults as $ result ) {
179
156
$ result = $ result ->get ();
@@ -230,11 +207,6 @@ public function begin(?string $database, ?float $timeout, BookmarkHolder $holder
230
207
$ this ->serverState = 'TX_READY ' ;
231
208
}
232
209
233
- public function getFactory (): BoltFactory
234
- {
235
- return $ this ->factory ;
236
- }
237
-
238
210
/**
239
211
* Discards a result.
240
212
*
@@ -273,7 +245,7 @@ public function discard(?int $qid): void
273
245
*/
274
246
public function run (string $ text , array $ parameters , ?string $ database , ?float $ timeout , BookmarkHolder $ holder ): array
275
247
{
276
- if (! str_starts_with ($ this ->serverState , ' TX_ ' ) || str_starts_with ( $ this -> getServerVersion () , '3 ' )) {
248
+ if (in_array ($ this ->serverState , [ ' STREAMING ' , 'TX_STREAMING ' ] )) {
277
249
$ this ->consumeResults ();
278
250
}
279
251
@@ -349,6 +321,11 @@ public function rollback(): void
349
321
$ this ->serverState = 'READY ' ;
350
322
}
351
323
324
+ public function protocol (): V3
325
+ {
326
+ return $ this ->boltProtocol ;
327
+ }
328
+
352
329
/**
353
330
* Pulls a result set.
354
331
*
@@ -363,10 +340,10 @@ public function pull(?int $qid, ?int $fetchSize): array
363
340
$ bolt = $ this ->protocol ();
364
341
try {
365
342
if (!$ bolt instanceof V4 ) {
366
- /** @var non-empty-list<list> */
343
+ /** @var non-empty-list<list> $tbr */
367
344
$ tbr = $ bolt ->pullAll ($ extra );
368
345
} else {
369
- /** @var non-empty-list<list> */
346
+ /** @var non-empty-list<list> $tbr */
370
347
$ tbr = $ bolt ->pull ($ extra );
371
348
}
372
349
} catch (MessageException $ e ) {
@@ -384,18 +361,17 @@ public function pull(?int $qid, ?int $fetchSize): array
384
361
return $ tbr ;
385
362
}
386
363
387
- /**
388
- * @psalm-mutation-free
389
- */
390
- public function getDriverConfiguration (): DriverConfiguration
391
- {
392
- return $ this ->config ->getDriverConfiguration ();
393
- }
394
-
395
364
public function __destruct ()
396
365
{
397
366
if ($ this ->serverState !== 'FAILED ' && $ this ->isOpen ()) {
398
- $ this ->close ();
367
+ if (in_array ($ this ->serverState , ['STREAMING ' , 'TX_STREAMING ' ])) {
368
+ $ this ->consumeResults ();
369
+ }
370
+
371
+ $ this ->protocol ()->goodbye ();
372
+
373
+ $ this ->serverState = 'DEFUNCT ' ;
374
+ unset($ this ->boltProtocol ); // has to be set to null as the sockets don't recover nicely contrary to what the underlying code might lead you to believe;
399
375
}
400
376
}
401
377
@@ -440,15 +416,6 @@ public function subscribeResult(CypherList $result): void
440
416
$ this ->subscribedResults [] = WeakReference::create ($ result );
441
417
}
442
418
443
- private function protocol (): V3
444
- {
445
- if ($ this ->boltProtocol === null ) {
446
- throw new LogicException ('Cannot use protocol if it is not created ' );
447
- }
448
-
449
- return $ this ->boltProtocol ;
450
- }
451
-
452
419
private function interpretResult (array $ result ): void
453
420
{
454
421
if (str_starts_with ($ this ->serverState , 'TX_ ' )) {
@@ -475,4 +442,9 @@ private function countResults(): int
475
442
476
443
return $ ctr ;
477
444
}
445
+
446
+ public function getUserAgent (): string
447
+ {
448
+ return $ this ->userAgent ;
449
+ }
478
450
}
0 commit comments