Skip to content

Commit 43c9f20

Browse files
authored
Merge pull request #258 from clue-labs/unhandled-rejection
Internal improvement to avoid unhandled rejection for future Promise API
2 parents eef95f0 + d2040a9 commit 43c9f20

File tree

2 files changed

+28
-5
lines changed

2 files changed

+28
-5
lines changed

src/HappyEyeBallsConnectionBuilder.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ public function connect()
8484

8585
$that->resolverPromises[Message::TYPE_AAAA] = $that->resolve(Message::TYPE_AAAA, $reject)->then($lookupResolve(Message::TYPE_AAAA));
8686
$that->resolverPromises[Message::TYPE_A] = $that->resolve(Message::TYPE_A, $reject)->then(function (array $ips) use ($that, &$timer) {
87-
// happy path: IPv6 has resolved already, continue with IPv4 addresses
88-
if ($that->resolved[Message::TYPE_AAAA] === true) {
87+
// happy path: IPv6 has resolved already (or could not resolve), continue with IPv4 addresses
88+
if ($that->resolved[Message::TYPE_AAAA] === true || !$ips) {
8989
return $ips;
9090
}
9191

@@ -117,8 +117,9 @@ public function connect()
117117
* @internal
118118
* @param int $type DNS query type
119119
* @param callable $reject
120-
* @return \React\Promise\PromiseInterface<string[],\Exception> Returns a promise
121-
* that resolves list of IP addresses on success or rejects with an \Exception on error.
120+
* @return \React\Promise\PromiseInterface<string[]> Returns a promise that
121+
* always resolves with a list of IP addresses on success or an empty
122+
* list on error.
122123
*/
123124
public function resolve($type, $reject)
124125
{
@@ -145,7 +146,8 @@ public function resolve($type, $reject)
145146
$reject(new \RuntimeException($that->error()));
146147
}
147148

148-
throw $e;
149+
// Exception already handled above, so don't throw an unhandled rejection here
150+
return array();
149151
});
150152
}
151153

tests/HappyEyeBallsConnectionBuilderTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,27 @@ public function testCancelConnectWillRejectPromiseAndCancelPendingIpv6Connection
677677
$this->assertEquals('Connection to tcp://reactphp.org:80 cancelled', $exception->getMessage());
678678
}
679679

680+
public function testResolveWillReturnResolvedPromiseWithEmptyListWhenDnsResolverFails()
681+
{
682+
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
683+
684+
$connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock();
685+
686+
$resolver = $this->getMockBuilder('React\Dns\Resolver\ResolverInterface')->getMock();
687+
$resolver->expects($this->once())->method('resolveAll')->with('reactphp.org', Message::TYPE_A)->willReturn(\React\Promise\reject(new \RuntimeException()));
688+
689+
$uri = 'tcp://reactphp.org:80';
690+
$host = 'reactphp.org';
691+
$parts = parse_url($uri);
692+
693+
$builder = new HappyEyeBallsConnectionBuilder($loop, $connector, $resolver, $uri, $host, $parts);
694+
695+
$promise = $builder->resolve(Message::TYPE_A, $this->expectCallableNever());
696+
697+
$this->assertInstanceof('React\Promise\PromiseInterface', $promise);
698+
$promise->then($this->expectCallableOnceWith(array()), $this->expectCallableNever());
699+
}
700+
680701
public function testAttemptConnectionWillConnectViaConnectorToGivenIpWithPortAndHostnameFromUriParts()
681702
{
682703
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();

0 commit comments

Comments
 (0)