Kaynağa Gözat

Implement PING in PUB/SUB loop abstraction for Redis 3.0.0.

Daniele Alessandri 10 yıl önce
ebeveyn
işleme
356f22a062

+ 12 - 0
src/PubSub/AbstractConsumer.php

@@ -26,6 +26,7 @@ abstract class AbstractConsumer implements Iterator
     const PUNSUBSCRIBE = 'punsubscribe';
     const MESSAGE      = 'message';
     const PMESSAGE     = 'pmessage';
+    const PONG         = 'pong';
 
     const STATUS_VALID       = 1;	// 0b0001
     const STATUS_SUBSCRIBED  = 2;	// 0b0010
@@ -95,6 +96,17 @@ abstract class AbstractConsumer implements Iterator
         $this->writeRequest(self::PUNSUBSCRIBE, func_get_args());
     }
 
+    /**
+     * 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->writeRequest('PING', array($payload));
+    }
+
     /**
      * Closes the context by unsubscribing from all the subscribed channels. The
      * context can be forcefully closed by dropping the underlying connection.

+ 6 - 0
src/PubSub/Consumer.php

@@ -137,6 +137,12 @@ class Consumer extends AbstractConsumer
                     'payload' => $response[3],
                 );
 
+            case self::PONG:
+                return (object) array(
+                    'kind'    => $response[0],
+                    'payload' => $response[1],
+                );
+
             default:
                 throw new ClientException(
                     "Unknown message type '{$response[0]}' received in the PUB/SUB context."

+ 37 - 1
tests/Predis/PubSub/ConsumerTest.php

@@ -145,6 +145,42 @@ class ConsumerTest extends PredisTestCase
         $this->assertNull($pubsub->next());
     }
 
+    /**
+     * @group disconnected
+     */
+    public function testHandlesPongMessages()
+    {
+        $rawmessage = array('pong', '');
+
+        $connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
+        $connection->expects($this->once())->method('read')->will($this->returnValue($rawmessage));
+
+        $client = new Client($connection);
+        $pubsub = new PubSubConsumer($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\NodeConnectionInterface');
+        $connection->expects($this->once())->method('read')->will($this->returnValue($rawmessage));
+
+        $client = new Client($connection);
+        $pubsub = new PubSubConsumer($client, array('subscribe' => 'channel:foo'));
+
+        $message = $pubsub->current();
+        $this->assertSame('pong', $message->kind);
+        $this->assertSame('foobar', $message->payload);
+    }
+
     /**
      * @group disconnected
      */
@@ -303,6 +339,6 @@ class ConsumerTest extends PredisTestCase
 
         $this->assertSame(array('message1', 'message2', 'QUIT'), $messages);
         $this->assertFalse($pubsub->valid());
-        $this->assertEquals('PONG', $consumer->ping());
+        $this->assertEquals('ECHO', $consumer->echo('ECHO'));
     }
 }