Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Promise v3 template types #145

Merged
merged 1 commit into from
Jul 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
}
}