1
0
mirror of https://github.com/danog/dns.git synced 2024-11-30 04:29:06 +01:00

Implement request sharing for concurrent requests to the same resource

This commit is contained in:
Niklas Keller 2017-06-23 17:48:03 +02:00
parent 1bd8870003
commit 9ed331ae3d
2 changed files with 29 additions and 1 deletions

View File

@ -30,6 +30,9 @@ class BasicResolver implements Resolver {
/** @var array */
private $servers = [];
/** @var array */
private $pendingQueries = [];
public function __construct(Cache $cache = null, ConfigLoader $configLoader = null) {
$this->cache = $cache ?? new ArrayCache;
$this->configLoader = $configLoader ?? \stripos(PHP_OS, "win") === 0
@ -134,7 +137,11 @@ class BasicResolver implements Resolver {
/** @inheritdoc */
public function query(string $name, int $type): Promise {
return call(function () use ($name, $type) {
if (isset($this->pendingQueries[$type . " " . $name])) {
return $this->pendingQueries[$type . " " . $name];
}
$promise = call(function () use ($name, $type) {
if (!$this->config) {
$this->config = yield $this->configLoader->loadConfig();
}
@ -209,6 +216,13 @@ class BasicResolver implements Resolver {
throw new ResolutionException("No response from any nameserver after {$attempts} attempts");
});
$this->pendingQueries[$type . " " . $name] = $promise;
$promise->onResolve(function () use ($name, $type) {
unset($this->pendingQueries[$type . " " . $name]);
});
return $promise;
}
/**

View File

@ -38,6 +38,20 @@ class IntegrationTest extends TestCase {
});
}
/**
* Test that two concurrent requests to the same resource share the same request and do not result in two requests
* being sent.
*/
public function testRequestSharing() {
Loop::run(function () {
$promise1 = Dns\query("example.com", Record::A);
$promise2 = Dns\query("example.com", Record::A);
$this->assertSame($promise1, $promise2);
$this->assertSame(yield $promise1, yield $promise2);
});
}
public function provideHostnames() {
return [
["google.com"],