Skip to content

Commit 3a84482

Browse files
authored
Merge pull request #89 from clue-labs/exception
Improve Exception messages for connection issues
2 parents b8582fa + 20859c2 commit 3a84482

File tree

5 files changed

+139
-10
lines changed

5 files changed

+139
-10
lines changed

examples/cli.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,10 @@
5050
});
5151
}, function (Exception $error) {
5252
echo 'CONNECTION ERROR: ' . $error->getMessage() . PHP_EOL;
53+
if ($error->getPrevious()) {
54+
echo $error->getPrevious()->getMessage() . PHP_EOL;
55+
}
5356
exit(1);
5457
});
5558

56-
5759
$loop->run();

examples/incr.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212

1313
$client->get('test')->then(function ($result) {
1414
var_dump($result);
15+
}, function (Exception $e) {
16+
echo 'Error: ' . $e->getMessage() . PHP_EOL;
17+
if ($e->getPrevious()) {
18+
echo $e->getPrevious()->getMessage() . PHP_EOL;
19+
}
20+
exit(1);
1521
});
1622

1723
$client->end();

examples/publish.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@
1212

1313
$client = $factory->createLazyClient('localhost');
1414
$client->publish($channel, $message)->then(function ($received) {
15-
echo 'successfully published. Received by ' . $received . PHP_EOL;
15+
echo 'Successfully published. Received by ' . $received . PHP_EOL;
16+
}, function (Exception $e) {
17+
echo 'Unable to publish: ' . $e->getMessage() . PHP_EOL;
18+
if ($e->getPrevious()) {
19+
echo $e->getPrevious()->getMessage() . PHP_EOL;
20+
}
21+
exit(1);
1622
});
1723

1824
$client->end();

src/Factory.php

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public function createClient($target)
5555
$connecting = $this->connector->connect($parts['authority']);
5656
$deferred = new Deferred(function ($_, $reject) use ($connecting) {
5757
// connection cancelled, start with rejecting attempt, then clean up
58-
$reject(new \RuntimeException('Connection to database server cancelled'));
58+
$reject(new \RuntimeException('Connection to Redis server cancelled'));
5959

6060
// either close successful connection or cancel pending connection attempt
6161
$connecting->then(function (ConnectionInterface $connection) {
@@ -67,6 +67,12 @@ public function createClient($target)
6767
$protocol = $this->protocol;
6868
$promise = $connecting->then(function (ConnectionInterface $stream) use ($protocol) {
6969
return new StreamingClient($stream, $protocol->createResponseParser(), $protocol->createSerializer());
70+
}, function (\Exception $e) {
71+
throw new \RuntimeException(
72+
'Connection to Redis server failed because underlying transport connection failed',
73+
0,
74+
$e
75+
);
7076
});
7177

7278
if (isset($parts['auth'])) {
@@ -77,7 +83,12 @@ function () use ($client) {
7783
},
7884
function ($error) use ($client) {
7985
$client->close();
80-
throw $error;
86+
87+
throw new \RuntimeException(
88+
'Connection to Redis server failed because AUTH command failed',
89+
0,
90+
$error
91+
);
8192
}
8293
);
8394
});
@@ -91,7 +102,12 @@ function () use ($client) {
91102
},
92103
function ($error) use ($client) {
93104
$client->close();
94-
throw $error;
105+
106+
throw new \RuntimeException(
107+
'Connection to Redis server failed because SELECT command failed',
108+
0,
109+
$error
110+
);
95111
}
96112
);
97113
});
@@ -108,7 +124,7 @@ function ($error) use ($client) {
108124
return \React\Promise\Timer\timeout($deferred->promise(), $timeout, $this->loop)->then(null, function ($e) {
109125
if ($e instanceof TimeoutException) {
110126
throw new \RuntimeException(
111-
'Connection to database server timed out after ' . $e->getTimeout() . ' seconds'
127+
'Connection to Redis server timed out after ' . $e->getTimeout() . ' seconds'
112128
);
113129
}
114130
throw $e;

tests/FactoryStreamingClientTest.php

Lines changed: 103 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,43 @@ public function testWillWriteAuthCommandIfRedisUnixUriContainsUserInfo()
131131
$this->factory->createClient('redis+unix://hello:world@/tmp/redis.sock');
132132
}
133133

134+
public function testWillResolveWhenAuthCommandReceivesOkResponseIfRedisUriContainsUserInfo()
135+
{
136+
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('write'))->getMock();
137+
$stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nworld\r\n");
138+
139+
$this->connector->expects($this->once())->method('connect')->willReturn(Promise\resolve($stream));
140+
$promise = $this->factory->createClient('redis://:world@localhost');
141+
142+
$stream->emit('data', array("+OK\r\n"));
143+
144+
$promise->then($this->expectCallableOnceWith($this->isInstanceOf('Clue\React\Redis\Client')));
145+
}
146+
147+
public function testWillRejectAndCloseAutomaticallyWhenAuthCommandReceivesErrorResponseIfRedisUriContainsUserInfo()
148+
{
149+
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('write', 'close'))->getMock();
150+
$stream->expects($this->once())->method('write')->with("*2\r\n$4\r\nauth\r\n$5\r\nworld\r\n");
151+
$stream->expects($this->once())->method('close');
152+
153+
$this->connector->expects($this->once())->method('connect')->willReturn(Promise\resolve($stream));
154+
$promise = $this->factory->createClient('redis://:world@localhost');
155+
156+
$stream->emit('data', array("-ERR invalid password\r\n"));
157+
158+
$promise->then(null, $this->expectCallableOnceWith(
159+
$this->logicalAnd(
160+
$this->isInstanceOf('RuntimeException'),
161+
$this->callback(function (\Exception $e) {
162+
return $e->getMessage() === 'Connection to Redis server failed because AUTH command failed';
163+
}),
164+
$this->callback(function (\Exception $e) {
165+
return $e->getPrevious()->getMessage() === 'ERR invalid password';
166+
})
167+
)
168+
));
169+
}
170+
134171
public function testWillWriteSelectCommandIfRedisUnixUriContainsDbQueryParameter()
135172
{
136173
$stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock();
@@ -140,19 +177,63 @@ public function testWillWriteSelectCommandIfRedisUnixUriContainsDbQueryParameter
140177
$this->factory->createClient('redis+unix:///tmp/redis.sock?db=demo');
141178
}
142179

180+
public function testWillResolveWhenSelectCommandReceivesOkResponseIfRedisUriContainsPath()
181+
{
182+
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('write'))->getMock();
183+
$stream->expects($this->once())->method('write')->with("*2\r\n$6\r\nselect\r\n$3\r\n123\r\n");
184+
185+
$this->connector->expects($this->once())->method('connect')->willReturn(Promise\resolve($stream));
186+
$promise = $this->factory->createClient('redis://localhost/123');
187+
188+
$stream->emit('data', array("+OK\r\n"));
189+
190+
$promise->then($this->expectCallableOnceWith($this->isInstanceOf('Clue\React\Redis\Client')));
191+
}
192+
193+
public function testWillRejectAndCloseAutomaticallyWhenSelectCommandReceivesErrorResponseIfRedisUriContainsPath()
194+
{
195+
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('write', 'close'))->getMock();
196+
$stream->expects($this->once())->method('write')->with("*2\r\n$6\r\nselect\r\n$3\r\n123\r\n");
197+
$stream->expects($this->once())->method('close');
198+
199+
$this->connector->expects($this->once())->method('connect')->willReturn(Promise\resolve($stream));
200+
$promise = $this->factory->createClient('redis://localhost/123');
201+
202+
$stream->emit('data', array("-ERR DB index is out of range\r\n"));
203+
204+
$promise->then(null, $this->expectCallableOnceWith(
205+
$this->logicalAnd(
206+
$this->isInstanceOf('RuntimeException'),
207+
$this->callback(function (\Exception $e) {
208+
return $e->getMessage() === 'Connection to Redis server failed because SELECT command failed';
209+
}),
210+
$this->callback(function (\Exception $e) {
211+
return $e->getPrevious()->getMessage() === 'ERR DB index is out of range';
212+
})
213+
)
214+
));
215+
}
216+
143217
public function testWillRejectIfConnectorRejects()
144218
{
145219
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:2')->willReturn(Promise\reject(new \RuntimeException()));
146220
$promise = $this->factory->createClient('redis://127.0.0.1:2');
147221

148-
$this->expectPromiseReject($promise);
222+
$promise->then(null, $this->expectCallableOnceWith(
223+
$this->logicalAnd(
224+
$this->isInstanceOf('RuntimeException'),
225+
$this->callback(function (\Exception $e) {
226+
return $e->getMessage() === 'Connection to Redis server failed because underlying transport connection failed';
227+
})
228+
)
229+
));
149230
}
150231

151232
public function testWillRejectIfTargetIsInvalid()
152233
{
153234
$promise = $this->factory->createClient('http://invalid target');
154235

155-
$this->expectPromiseReject($promise);
236+
$promise->then(null, $this->expectCallableOnceWith($this->isInstanceOf('InvalidArgumentException')));
156237
}
157238

158239
public function testCancelWillRejectPromise()
@@ -173,6 +254,15 @@ public function testCancelWillCancelConnectorWhenConnectionIsPending()
173254

174255
$promise = $this->factory->createClient('redis://127.0.0.1:2');
175256
$promise->cancel();
257+
258+
$promise->then(null, $this->expectCallableOnceWith(
259+
$this->logicalAnd(
260+
$this->isInstanceOf('RuntimeException'),
261+
$this->callback(function (\Exception $e) {
262+
return $e->getMessage() === 'Connection to Redis server cancelled';
263+
})
264+
)
265+
));
176266
}
177267

178268
public function testCancelWillCloseConnectionWhenConnectionWaitsForSelect()
@@ -185,6 +275,15 @@ public function testCancelWillCloseConnectionWhenConnectionWaitsForSelect()
185275

186276
$promise = $this->factory->createClient('redis://127.0.0.1:2/123');
187277
$promise->cancel();
278+
279+
$promise->then(null, $this->expectCallableOnceWith(
280+
$this->logicalAnd(
281+
$this->isInstanceOf('RuntimeException'),
282+
$this->callback(function (\Exception $e) {
283+
return $e->getMessage() === 'Connection to Redis server cancelled';
284+
})
285+
)
286+
));
188287
}
189288

190289
public function testCreateClientWithTimeoutParameterWillStartTimerAndRejectOnExplicitTimeout()
@@ -205,9 +304,9 @@ public function testCreateClientWithTimeoutParameterWillStartTimerAndRejectOnExp
205304

206305
$promise->then(null, $this->expectCallableOnceWith(
207306
$this->logicalAnd(
208-
$this->isInstanceOf('Exception'),
307+
$this->isInstanceOf('RuntimeException'),
209308
$this->callback(function (\Exception $e) {
210-
return $e->getMessage() === 'Connection to database server timed out after 0 seconds';
309+
return $e->getMessage() === 'Connection to Redis server timed out after 0 seconds';
211310
})
212311
)
213312
));

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy