Переглянути джерело

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

Daniele Alessandri 11 роки тому
батько
коміт
f6e97d4b94

+ 12 - 0
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.
      *

+ 6 - 0
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);

+ 34 - 1
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'));
     }
 }