-
Notifications
You must be signed in to change notification settings - Fork 40
Expand file tree
/
Copy pathBoltFactory.php
More file actions
114 lines (94 loc) · 4.24 KB
/
Copy pathBoltFactory.php
File metadata and controls
114 lines (94 loc) · 4.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<?php
declare(strict_types=1);
/*
* This file is part of the Neo4j PHP Client and Driver package.
*
* (c) Nagels <https://nagels.tech>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Laudis\Neo4j;
use Laudis\Neo4j\Bolt\BoltConnection;
use Laudis\Neo4j\Bolt\ProtocolFactory;
use Laudis\Neo4j\Bolt\SslConfigurationFactory;
use Laudis\Neo4j\Bolt\SystemWideConnectionFactory;
use Laudis\Neo4j\Bolt\UriConfiguration;
use Laudis\Neo4j\Common\ConnectionConfiguration;
use Laudis\Neo4j\Common\Neo4jLogger;
use Laudis\Neo4j\Contracts\BasicConnectionFactoryInterface;
use Laudis\Neo4j\Contracts\ConnectionInterface;
use Laudis\Neo4j\Databags\ConnectionRequestData;
use Laudis\Neo4j\Databags\DatabaseInfo;
use Laudis\Neo4j\Databags\DriverConfiguration;
use Laudis\Neo4j\Databags\SessionConfiguration;
use Laudis\Neo4j\Enum\ConnectionProtocol;
use Laudis\Neo4j\Enum\SocketType;
/**
* Small wrapper around the bolt library to create and authenticate Bolt connections (protocol 4.4+).
*/
class BoltFactory
{
/**
* @psalm-external-mutation-free
*/
public function __construct(
private readonly BasicConnectionFactoryInterface $connectionFactory,
private readonly ProtocolFactory $protocolFactory,
private readonly SslConfigurationFactory $sslConfigurationFactory,
private readonly ?Neo4jLogger $logger = null,
) {
}
public static function create(?Neo4jLogger $logger, ?SocketType $socketType = null): self
{
return new self(SystemWideConnectionFactory::getInstance($socketType), new ProtocolFactory(), new SslConfigurationFactory(), $logger);
}
public function createConnection(ConnectionRequestData $data, SessionConfiguration $sessionConfig): BoltConnection
{
[$sslLevel, $sslConfig] = $this->sslConfigurationFactory->create($data->getUri()->withHost($data->getHostname()), $data->getSslConfig());
$socketTimeout = $data->getSocketTimeoutSeconds() ?? DriverConfiguration::DEFAULT_SOCKET_TIMEOUT;
$uriConfig = new UriConfiguration(
$data->getUri()->getHost(),
$data->getUri()->getPort(),
$sslLevel,
$sslConfig,
$socketTimeout,
$this->logger?->getLogger()
);
$connection = $this->connectionFactory->create($uriConfig);
$protocol = $this->protocolFactory->createProtocol($connection->getIConnection());
$config = new ConnectionConfiguration(
'',
$data->getUri(),
ConnectionProtocol::determineBoltVersion($protocol),
$sessionConfig->getAccessMode(),
$sessionConfig->getDatabase() === null ? null : new DatabaseInfo($sessionConfig->getDatabase()),
$sslLevel
);
$connection = new BoltConnection($protocol, $connection, $data->getAuth(), $data->getUserAgent(), $config, $this->logger, $socketTimeout);
$response = $data->getAuth()->authenticateBolt($connection, $data->getUserAgent());
$config->setServerAgent($response['server'] ?? '');
// Timeout precedence: 1) driver config, 2) server hint, 3) default 30s.
// Only use server hint when driver did not explicitly configure a timeout.
$driverHasExplicitTimeout = $data->getSocketTimeoutSeconds() !== null;
if (!$driverHasExplicitTimeout && array_key_exists('hints', $response) && array_key_exists('connection.recv_timeout_seconds', $response['hints'])) {
$connection->setRecvTimeoutHint((float) $response['hints']['connection.recv_timeout_seconds']);
}
return $connection;
}
public function canReuseConnection(ConnectionInterface $connection, SessionConfiguration $config): bool
{
if (!$connection->isOpen()) {
return false;
}
$databaseInfo = $connection->getDatabaseInfo();
$database = $databaseInfo?->getName();
return $connection->getAccessMode() === $config->getAccessMode()
&& $database === $config->getDatabase();
}
public function reuseConnection(BoltConnection $connection, SessionConfiguration $sessionConfig): BoltConnection
{
// TODO make sure session config gets merged
return $connection;
}
}