diff --git a/lib/Predis/PubSub/AbstractPubSubContext.php b/lib/Predis/PubSub/AbstractPubSubContext.php index d1e83dee..78c264d4 100644 --- a/lib/Predis/PubSub/AbstractPubSubContext.php +++ b/lib/Predis/PubSub/AbstractPubSubContext.php @@ -24,6 +24,7 @@ abstract class AbstractPubSubContext implements \Iterator const PUNSUBSCRIBE = 'punsubscribe'; const MESSAGE = 'message'; const PMESSAGE = 'pmessage'; + const PONG = 'pong'; const STATUS_VALID = 1; // 0b0001 const STATUS_SUBSCRIBED = 2; // 0b0010 @@ -51,6 +52,17 @@ abstract class AbstractPubSubContext implements \Iterator return ($this->statusFlags & $value) === $value; } + /** + * PING the server with an optional payload that will be echoed as a + * PONG message in the pub/sub loop. + * + * @param string $payload Optional PING payload. + */ + public function ping($payload = null) + { + $this->writeCommand('PING', array($payload)); + } + /** * Subscribes to the specified channels. * diff --git a/lib/Predis/PubSub/PubSubContext.php b/lib/Predis/PubSub/PubSubContext.php index c01f3c0b..7657a9c3 100644 --- a/lib/Predis/PubSub/PubSubContext.php +++ b/lib/Predis/PubSub/PubSubContext.php @@ -133,6 +133,12 @@ class PubSubContext extends AbstractPubSubContext 'payload' => $response[3], ); + case self::PONG: + return (object) array( + 'kind' => $response[0], + 'payload' => $response[1], + ); + default: $message = "Received an unknown message type {$response[0]} inside of a pubsub context"; throw new ClientException($message); diff --git a/tests/Predis/PubSub/PubSubContextTest.php b/tests/Predis/PubSub/PubSubContextTest.php index 1cbe8af2..a53d9858 100644 --- a/tests/Predis/PubSub/PubSubContextTest.php +++ b/tests/Predis/PubSub/PubSubContextTest.php @@ -144,6 +144,39 @@ class PubSubContextTest extends PredisTestCase $this->assertNull($pubsub->next()); } + public function testHandlesPongMessages() + { + $rawmessage = array('pong', ''); + + $connection = $this->getMock('Predis\Connection\SingleConnectionInterface'); + $connection->expects($this->once())->method('read')->will($this->returnValue($rawmessage)); + + $client = new Client($connection); + $pubsub = new PubSubContext($client, array('subscribe' => 'channel:foo')); + + $message = $pubsub->current(); + $this->assertSame('pong', $message->kind); + $this->assertSame('', $message->payload); + } + + /** + * @group disconnected + */ + public function testHandlesPongMessagesWithPayload() + { + $rawmessage = array('pong', 'foobar'); + + $connection = $this->getMock('Predis\Connection\SingleConnectionInterface'); + $connection->expects($this->once())->method('read')->will($this->returnValue($rawmessage)); + + $client = new Client($connection); + $pubsub = new PubSubContext($client, array('subscribe' => 'channel:foo')); + + $message = $pubsub->current(); + $this->assertSame('pong', $message->kind); + $this->assertSame('foobar', $message->payload); + } + /** * @group disconnected */ @@ -302,6 +335,6 @@ class PubSubContextTest extends PredisTestCase $this->assertSame(array('message1', 'message2', 'QUIT'), $messages); $this->assertFalse($pubsub->valid()); - $this->assertTrue($consumer->ping()); + $this->assertEquals('ECHO', $consumer->echo('ECHO')); } }