public function subscribe($channels, $callback)
{
if (!$this->standalone) {
return $this->__call('subscribe', array((array) $channels, $callback));
}
// Standalone mode: use infinite loop to subscribe until timeout
$channelCount = is_array($channels) ? count($channels) : 1;
while ($channelCount--) {
if (isset($status)) {
list($command, $channel, $status) = $this->read_reply();
} else {
list($command, $channel, $status) = $this->__call('subscribe', array($channels));
}
$this->subscribed = $status > 0;
if (!$status) {
throw new CredisException('Invalid subscribe response.');
}
}
try {
while ($this->subscribed) {
list($type, $channel, $message) = $this->read_reply();
if ($type != 'message') {
throw new CredisException('Received non-message reply.');
}
$callback($this, $channel, $message);
}
} catch (CredisException $e) {
if ($e->getCode() == CredisException::CODE_TIMED_OUT) {
try {
list($command, $channel, $status) = $this->unsubscribe($channels);
while ($status !== 0) {
list($command, $channel, $status) = $this->read_reply();
}
} catch (CredisException $e2) {
throw $e2;
}
}
throw $e;
}
}
public function testPubsub() { $timeout = 2; $time = time(); $this->credis->setReadTimeout($timeout); try { $testCase = $this; $this->credis->pSubscribe(array('foobar', 'test*'), function ($credis, $pattern, $channel, $message) use($testCase, &$time) { $time = time(); // Reset timeout // Test using: redis-cli publish foobar blah $testCase->assertEquals('blah', $message); }); $this->fail('pSubscribe should not return.'); } catch (CredisException $e) { $this->assertEquals($timeout, time() - $time); if ($this->useStandalone) { // phpredis does not distinguish between timed out and disconnected $this->assertEquals($e->getCode(), CredisException::CODE_TIMED_OUT); } else { $this->assertEquals($e->getCode(), CredisException::CODE_DISCONNECTED); } } // Perform a new subscription. Client should have either unsubscribed or disconnected $timeout = 2; $time = time(); $this->credis->setReadTimeout($timeout); try { $testCase = $this; $this->credis->subscribe('foobar', function ($credis, $channel, $message) use($testCase, &$time) { $time = time(); // Reset timeout // Test using: redis-cli publish foobar blah $testCase->assertEquals('blah', $message); }); $this->fail('subscribe should not return.'); } catch (CredisException $e) { $this->assertEquals($timeout, time() - $time); if ($this->useStandalone) { // phpredis does not distinguish between timed out and disconnected $this->assertEquals($e->getCode(), CredisException::CODE_TIMED_OUT); } else { $this->assertEquals($e->getCode(), CredisException::CODE_DISCONNECTED); } } }