diff --git a/README.md b/README.md index d674a369..a044df7b 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,21 @@ $loop->run(); If the first call returns before the second, only one query will be executed. The second result will be served from cache. +### Custom cache adapter + +By default, the above will use an in memory cache. + +You can also specify a custom cache implementing [`CacheInterface`](https://github.com/reactphp/cache) to handle the record cache instead: + +```php +$cache = new React\Cache\ArrayCache(); +$loop = React\EventLoop\Factory::create(); +$factory = new React\Dns\Resolver\Factory(); +$dns = $factory->createCached('8.8.8.8', $loop, $cache); +``` + +See also the wiki for possible [cache implementations](https://github.com/reactphp/react/wiki/Users#cache-implementations). + ## Install The recommended way to install this library is [through Composer](http://getcomposer.org). diff --git a/src/Resolver/Factory.php b/src/Resolver/Factory.php index a2aa801a..1e210a8e 100644 --- a/src/Resolver/Factory.php +++ b/src/Resolver/Factory.php @@ -3,6 +3,7 @@ namespace React\Dns\Resolver; use React\Cache\ArrayCache; +use React\Cache\CacheInterface; use React\Dns\Query\Executor; use React\Dns\Query\CachedExecutor; use React\Dns\Query\RecordCache; @@ -21,10 +22,14 @@ public function create($nameserver, LoopInterface $loop) return new Resolver($nameserver, $executor); } - public function createCached($nameserver, LoopInterface $loop) + public function createCached($nameserver, LoopInterface $loop, CacheInterface $cache = null) { + if (!($cache instanceof CacheInterface)) { + $cache = new ArrayCache(); + } + $nameserver = $this->addPortToServerIfMissing($nameserver); - $executor = $this->createCachedExecutor($loop); + $executor = $this->createCachedExecutor($loop, $cache); return new Resolver($nameserver, $executor); } @@ -39,9 +44,9 @@ protected function createRetryExecutor(LoopInterface $loop) return new RetryExecutor($this->createExecutor($loop)); } - protected function createCachedExecutor(LoopInterface $loop) + protected function createCachedExecutor(LoopInterface $loop, CacheInterface $cache) { - return new CachedExecutor($this->createRetryExecutor($loop), new RecordCache(new ArrayCache())); + return new CachedExecutor($this->createRetryExecutor($loop), new RecordCache($cache)); } protected function addPortToServerIfMissing($nameserver) diff --git a/tests/Resolver/FactoryTest.php b/tests/Resolver/FactoryTest.php index d4f47719..6b3b9ac8 100644 --- a/tests/Resolver/FactoryTest.php +++ b/tests/Resolver/FactoryTest.php @@ -39,7 +39,30 @@ public function createCachedShouldCreateResolverWithCachedExecutor() $resolver = $factory->createCached('8.8.8.8:53', $loop); $this->assertInstanceOf('React\Dns\Resolver\Resolver', $resolver); - $this->assertInstanceOf('React\Dns\Query\CachedExecutor', $this->getResolverPrivateMemberValue($resolver, 'executor')); + $executor = $this->getResolverPrivateMemberValue($resolver, 'executor'); + $this->assertInstanceOf('React\Dns\Query\CachedExecutor', $executor); + $recordCache = $this->getCachedExecutorPrivateMemberValue($executor, 'cache'); + $recordCacheCache = $this->getRecordCachePrivateMemberValue($recordCache, 'cache'); + $this->assertInstanceOf('React\Cache\CacheInterface', $recordCacheCache); + $this->assertInstanceOf('React\Cache\ArrayCache', $recordCacheCache); + } + + /** @test */ + public function createCachedShouldCreateResolverWithCachedExecutorWithCustomCache() + { + $cache = $this->getMock('React\Cache\CacheInterface'); + $loop = $this->getMock('React\EventLoop\LoopInterface'); + + $factory = new Factory(); + $resolver = $factory->createCached('8.8.8.8:53', $loop, $cache); + + $this->assertInstanceOf('React\Dns\Resolver\Resolver', $resolver); + $executor = $this->getResolverPrivateMemberValue($resolver, 'executor'); + $this->assertInstanceOf('React\Dns\Query\CachedExecutor', $executor); + $recordCache = $this->getCachedExecutorPrivateMemberValue($executor, 'cache'); + $recordCacheCache = $this->getRecordCachePrivateMemberValue($recordCache, 'cache'); + $this->assertInstanceOf('React\Cache\CacheInterface', $recordCacheCache); + $this->assertSame($cache, $recordCacheCache); } /** @@ -75,4 +98,18 @@ private function getResolverPrivateMemberValue($resolver, $field) $reflector->setAccessible(true); return $reflector->getValue($resolver); } + + private function getCachedExecutorPrivateMemberValue($resolver, $field) + { + $reflector = new \ReflectionProperty('React\Dns\Query\CachedExecutor', $field); + $reflector->setAccessible(true); + return $reflector->getValue($resolver); + } + + private function getRecordCachePrivateMemberValue($resolver, $field) + { + $reflector = new \ReflectionProperty('React\Dns\Query\RecordCache', $field); + $reflector->setAccessible(true); + return $reflector->getValue($resolver); + } }