Skip to content

Commit 89cb777

Browse files
committed
implemented DNS address resolving during intial routing table fetch cycle
1 parent e13d5df commit 89cb777

File tree

3 files changed

+28
-10
lines changed

3 files changed

+28
-10
lines changed

src/Common/DNSAddressResolver.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,12 @@ public function getAddresses(string $host): iterable
3131
// as late as possible
3232
yield $host;
3333

34+
/** @var list<array{ip?: string|null}> $records */
3435
$records = dns_get_record($host, DNS_A | DNS_AAAA);
3536
if (count($records) === 0) {
3637
yield from $this->tryReverseLookup($host);
3738
} else {
38-
$records = array_map(static fn (array $x): string => $x['ip'] ?? '', $records);
39+
$records = array_map(static fn (array $x) => $x['ip'] ?? '', $records);
3940
$records = array_filter($records, static fn (string $x) => $x !== '');
4041
yield from array_values(array_unique($records));
4142
}
@@ -46,9 +47,10 @@ public function getAddresses(string $host): iterable
4647
*/
4748
private function tryReverseLookup(string $host): iterable
4849
{
50+
/** @var list<array{target?: string|null}> $records */
4951
$records = dns_get_record($host.'.in-addr.arpa');
5052
if (count($records) !== 0) {
51-
$records = array_map(static fn (array $x): string => $x['target'] ?? '', $records);
53+
$records = array_map(static fn (array $x) => $x['target'] ?? '', $records);
5254
$records = array_filter($records, static fn (string $x) => $x !== '');
5355
yield from array_values(array_unique($records));
5456
}

src/Neo4j/Neo4jConnectionPool.php

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use Laudis\Neo4j\Bolt\BoltConnection;
2525
use Laudis\Neo4j\Bolt\BoltConnectionPool;
2626
use Laudis\Neo4j\Common\Uri;
27+
use Laudis\Neo4j\Contracts\AddressResolverInterface;
2728
use Laudis\Neo4j\Contracts\AuthenticateInterface;
2829
use Laudis\Neo4j\Contracts\ConnectionInterface;
2930
use Laudis\Neo4j\Contracts\ConnectionPoolInterface;
@@ -32,6 +33,8 @@
3233
use Laudis\Neo4j\Enum\RoutingRoles;
3334
use Psr\Http\Message\UriInterface;
3435
use function random_int;
36+
use RuntimeException;
37+
use function sprintf;
3538
use function str_starts_with;
3639
use function time;
3740

@@ -52,13 +55,15 @@ final class Neo4jConnectionPool implements ConnectionPoolInterface
5255
private static array $routingCache = [];
5356
/** @psalm-readonly */
5457
private BoltConnectionPool $pool;
58+
private AddressResolverInterface $resolver;
5559

5660
/**
5761
* @psalm-mutation-free
5862
*/
59-
public function __construct(BoltConnectionPool $pool)
63+
public function __construct(BoltConnectionPool $pool, AddressResolverInterface $resolver)
6064
{
6165
$this->pool = $pool;
66+
$this->resolver = $resolver;
6267
}
6368

6469
/**
@@ -73,10 +78,20 @@ public function acquire(
7378

7479
$table = self::$routingCache[$key] ?? null;
7580
if ($table === null || $table->getTtl() < time()) {
76-
$connection = $this->pool->acquire($uri, $authenticate, $config);
77-
$table = $this->routingTable($connection, $config);
78-
self::$routingCache[$key] = $table;
79-
$connection->close();
81+
$addresses = $this->resolver->getAddresses($uri->getHost());
82+
$triedAddresses = [];
83+
foreach ($addresses as $address) {
84+
$triedAddresses[] = $address;
85+
if ($this->pool->canConnect($uri->withHost($address), $authenticate)) {
86+
$connection = $this->pool->acquire($uri->withHost($address), $authenticate, $config);
87+
$table = $this->routingTable($connection, $config);
88+
self::$routingCache[$key] = $table;
89+
$connection->close();
90+
break;
91+
}
92+
}
93+
94+
throw new RuntimeException(sprintf('Cannot connect to address: "%s". Addresses tried: "%s"', $uri->getHost(), implode('", "', $triedAddresses)));
8095
}
8196

8297
$server = $this->getNextServer($table, $config->getAccessMode()) ?? $uri;

src/Neo4j/Neo4jDriver.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Laudis\Neo4j\Authentication\Authenticate;
1919
use Laudis\Neo4j\Bolt\BoltConnectionPool;
2020
use Laudis\Neo4j\Bolt\Session;
21+
use Laudis\Neo4j\Common\DNSAddressResolver;
2122
use Laudis\Neo4j\Common\Uri;
2223
use Laudis\Neo4j\Contracts\AuthenticateInterface;
2324
use Laudis\Neo4j\Contracts\DriverInterface;
@@ -35,7 +36,7 @@
3536
*
3637
* @implements DriverInterface<T>
3738
*
38-
* @psalm-import-type OGMResults from \Laudis\Neo4j\Formatter\OGMFormatter
39+
* @psalm-import-type OGMResults from OGMFormatter
3940
*/
4041
final class Neo4jDriver implements DriverInterface
4142
{
@@ -86,15 +87,15 @@ public static function create($uri, ?DriverConfiguration $configuration = null,
8687
return new self(
8788
$uri,
8889
$authenticate ?? Authenticate::fromUrl($uri),
89-
new Neo4jConnectionPool(new BoltConnectionPool($configuration)),
90+
new Neo4jConnectionPool(new BoltConnectionPool($configuration), new DNSAddressResolver()),
9091
$formatter,
9192
);
9293
}
9394

9495
return new self(
9596
$uri,
9697
$authenticate ?? Authenticate::fromUrl($uri),
97-
new Neo4jConnectionPool(new BoltConnectionPool($configuration)),
98+
new Neo4jConnectionPool(new BoltConnectionPool($configuration), new DNSAddressResolver()),
9899
OGMFormatter::create(),
99100
);
100101
}

0 commit comments

Comments
 (0)