Skip to content

Commit

Permalink
Use Promise v3 template types
Browse files Browse the repository at this point in the history
  • Loading branch information
clue committed Jul 21, 2023
1 parent a39fa70 commit d4bd58e
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 29 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ given event loop instance.

#### __call()

The `__call(string $name, string[] $args): PromiseInterface<mixed,Exception>` method can be used to
The `__call(string $name, string[] $args): PromiseInterface<mixed>` 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.
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
2 changes: 1 addition & 1 deletion phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ parameters:

reportUnmatchedIgnoredErrors: false
ignoreErrors:
# ignore generic usage like `PromiseInterface<T>` until fixed upstream
# ignore generic usage like `PromiseInterface<T>` 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::.+\(\)\.$/'
Expand Down
8 changes: 5 additions & 3 deletions src/Io/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -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<StreamingClient,\Exception> Promise that will
* @return PromiseInterface<StreamingClient> Promise that will
* be fulfilled with `StreamingClient` on success or rejects with `\Exception` on error.
*/
public function createClient(string $uri): PromiseInterface
Expand Down Expand Up @@ -79,6 +79,8 @@ public function createClient(string $uri): PromiseInterface
$authority = 'unix://' . substr($parts['path'], 1);
unset($parts['path']);
}

/** @var PromiseInterface<ConnectionInterface> $connecting */
$connecting = $this->connector->connect($authority);

$deferred = new Deferred(function ($_, $reject) use ($connecting, $uri) {
Expand All @@ -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(),
Expand Down Expand Up @@ -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)',
Expand Down
7 changes: 5 additions & 2 deletions src/Io/StreamingClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class StreamingClient extends EventEmitter
/** @var SerializerInterface */
private $serializer;

/** @var Deferred[] */
/** @var Deferred<mixed>[] */
private $requests = [];

/** @var bool */
Expand Down Expand Up @@ -71,7 +71,10 @@ public function __construct(DuplexStreamInterface $stream, ParserInterface $pars
$this->serializer = $serializer;
}

/** @param string[] $args */
/**
* @param string[] $args
* @return PromiseInterface<mixed>
*/
public function __call(string $name, array $args): PromiseInterface
{
$request = new Deferred();
Expand Down
11 changes: 8 additions & 3 deletions src/RedisClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class RedisClient extends EventEmitter
/** @var bool */
private $closed = false;

/** @var ?PromiseInterface */
/** @var ?PromiseInterface<StreamingClient> */
private $promise = null;

/** @var LoopInterface */
Expand Down Expand Up @@ -76,6 +76,9 @@ public function __construct($url, ConnectorInterface $connector = null, LoopInte
$this->factory = new Factory($this->loop, $connector);
}

/**
* @return PromiseInterface<StreamingClient>
*/
private function client(): PromiseInterface
{
if ($this->promise !== null) {
Expand Down Expand Up @@ -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;

Expand All @@ -148,7 +153,7 @@ private function client(): PromiseInterface
*
* @param string $name
* @param string[] $args
* @return PromiseInterface Promise<mixed,Exception>
* @return PromiseInterface<mixed>
*/
public function __call(string $name, array $args): PromiseInterface
{
Expand Down
23 changes: 5 additions & 18 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,30 +48,17 @@ protected function createCallableMock(): MockObject
}
}

protected function expectPromiseResolve(PromiseInterface $promise): PromiseInterface
/**
* @param PromiseInterface<mixed> $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;
}
}

0 comments on commit d4bd58e

Please sign in to comment.