From d4bd58eb3ea77c9da4edc210938ad6b3ac67a7b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Fri, 14 Jul 2023 11:42:16 +0200 Subject: [PATCH] Use Promise v3 template types --- README.md | 2 +- composer.json | 2 +- phpstan.neon.dist | 2 +- src/Io/Factory.php | 8 +++++--- src/Io/StreamingClient.php | 7 +++++-- src/RedisClient.php | 11 ++++++++--- tests/TestCase.php | 23 +++++------------------ 7 files changed, 26 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 8e439fa..b143811 100644 --- a/README.md +++ b/README.md @@ -421,7 +421,7 @@ given event loop instance. #### __call() -The `__call(string $name, string[] $args): PromiseInterface` method can be used to +The `__call(string $name, string[] $args): PromiseInterface` method can be used to invoke the given command. This is a magic method that will be invoked when calling any Redis command on this instance. diff --git a/composer.json b/composer.json index a0cb588..c1414b3 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "evenement/evenement": "^3.0 || ^2.0 || ^1.0", "react/event-loop": "^1.2", "react/promise": "^3 || ^2.0 || ^1.1", - "react/promise-timer": "^1.9", + "react/promise-timer": "^1.10", "react/socket": "^1.12" }, "require-dev": { diff --git a/phpstan.neon.dist b/phpstan.neon.dist index f9fd7fb..fb725aa 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -8,7 +8,7 @@ parameters: reportUnmatchedIgnoredErrors: false ignoreErrors: - # ignore generic usage like `PromiseInterface` until fixed upstream + # ignore generic usage like `PromiseInterface` for Promise v2/v1 - '/^PHPDoc tag @return contains generic type React\\Promise\\PromiseInterface<.+> but interface React\\Promise\\PromiseInterface is not generic\.$/' # ignore undefined methods due to magic `__call()` method - '/^Call to an undefined method Clue\\React\\Redis\\RedisClient::.+\(\)\.$/' diff --git a/src/Io/Factory.php b/src/Io/Factory.php index c8b2b97..d70a08c 100644 --- a/src/Io/Factory.php +++ b/src/Io/Factory.php @@ -44,7 +44,7 @@ public function __construct(LoopInterface $loop = null, ConnectorInterface $conn * Create Redis client connected to address of given redis instance * * @param string $uri Redis server URI to connect to - * @return PromiseInterface Promise that will + * @return PromiseInterface Promise that will * be fulfilled with `StreamingClient` on success or rejects with `\Exception` on error. */ public function createClient(string $uri): PromiseInterface @@ -79,6 +79,8 @@ public function createClient(string $uri): PromiseInterface $authority = 'unix://' . substr($parts['path'], 1); unset($parts['path']); } + + /** @var PromiseInterface $connecting */ $connecting = $this->connector->connect($authority); $deferred = new Deferred(function ($_, $reject) use ($connecting, $uri) { @@ -100,7 +102,7 @@ public function createClient(string $uri): PromiseInterface $promise = $connecting->then(function (ConnectionInterface $stream) { return new StreamingClient($stream, $this->protocol->createResponseParser(), $this->protocol->createSerializer()); - }, function (\Exception $e) use ($uri) { + }, function (\Throwable $e) use ($uri) { throw new \RuntimeException( 'Connection to ' . $uri . ' failed: ' . $e->getMessage(), $e->getCode(), @@ -175,7 +177,7 @@ function (\Exception $e) use ($redis, $uri) { return $deferred->promise(); } - return timeout($deferred->promise(), $timeout, $this->loop)->then(null, function ($e) use ($uri) { + return timeout($deferred->promise(), $timeout, $this->loop)->then(null, function (\Throwable $e) use ($uri) { if ($e instanceof TimeoutException) { throw new \RuntimeException( 'Connection to ' . $uri . ' timed out after ' . $e->getTimeout() . ' seconds (ETIMEDOUT)', diff --git a/src/Io/StreamingClient.php b/src/Io/StreamingClient.php index 1dc2fde..bb7689f 100644 --- a/src/Io/StreamingClient.php +++ b/src/Io/StreamingClient.php @@ -24,7 +24,7 @@ class StreamingClient extends EventEmitter /** @var SerializerInterface */ private $serializer; - /** @var Deferred[] */ + /** @var Deferred[] */ private $requests = []; /** @var bool */ @@ -71,7 +71,10 @@ public function __construct(DuplexStreamInterface $stream, ParserInterface $pars $this->serializer = $serializer; } - /** @param string[] $args */ + /** + * @param string[] $args + * @return PromiseInterface + */ public function __call(string $name, array $args): PromiseInterface { $request = new Deferred(); diff --git a/src/RedisClient.php b/src/RedisClient.php index 9ad7027..6fa991c 100644 --- a/src/RedisClient.php +++ b/src/RedisClient.php @@ -37,7 +37,7 @@ class RedisClient extends EventEmitter /** @var bool */ private $closed = false; - /** @var ?PromiseInterface */ + /** @var ?PromiseInterface */ private $promise = null; /** @var LoopInterface */ @@ -76,6 +76,9 @@ public function __construct($url, ConnectorInterface $connector = null, LoopInte $this->factory = new Factory($this->loop, $connector); } + /** + * @return PromiseInterface + */ private function client(): PromiseInterface { if ($this->promise !== null) { @@ -132,7 +135,9 @@ private function client(): PromiseInterface ); return $redis; - }, function (\Exception $e) { + }, function (\Throwable $e) { + assert($e instanceof \Exception); + // connection failed => discard connection attempt $this->promise = null; @@ -148,7 +153,7 @@ private function client(): PromiseInterface * * @param string $name * @param string[] $args - * @return PromiseInterface Promise + * @return PromiseInterface */ public function __call(string $name, array $args): PromiseInterface { diff --git a/tests/TestCase.php b/tests/TestCase.php index b79f7ab..483864d 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -48,30 +48,17 @@ protected function createCallableMock(): MockObject } } - protected function expectPromiseResolve(PromiseInterface $promise): PromiseInterface + /** + * @param PromiseInterface $promise + */ + protected function expectPromiseResolve(PromiseInterface $promise): void { $this->assertInstanceOf(PromiseInterface::class, $promise); - $promise->then(null, function(\Exception $error) { + $promise->then(null, function(\Throwable $error) { $this->assertNull($error); $this->fail('promise rejected'); }); $promise->then($this->expectCallableOnce(), $this->expectCallableNever()); - - return $promise; - } - - protected function expectPromiseReject(PromiseInterface $promise): PromiseInterface - { - $this->assertInstanceOf(PromiseInterface::class, $promise); - - $promise->then(function($value) { - $this->assertNull($value); - $this->fail('promise resolved'); - }); - - $promise->then($this->expectCallableNever(), $this->expectCallableOnce()); - - return $promise; } }