浏览代码

Tweak phpdocs and API of streamable multibulk iterators.

Despite not being a globally supported feature of Predis anymore, they
are still optionally supported by our default text protocol processors
and they can be used to build custom stuff for specific needs.
Daniele Alessandri 11 年之前
父节点
当前提交
1a7b604c1b

+ 20 - 12
lib/Predis/Iterator/MultiBulkResponse.php

@@ -11,19 +11,27 @@
 
 namespace Predis\Iterator;
 
+use Iterator;
+use Countable;
 use Predis\ResponseObjectInterface;
 
 /**
- * Iterator that abstracts the access to multibulk replies and allows
- * them to be consumed by user's code in a streaming fashion.
+ * Iterator that abstracts the access to multibulk responses allowing them to be
+ * consumed in a streamable fashion without keeping the whole payload in memory.
+ *
+ * This iterator does not support rewinding which means that the iteration, once
+ * consumed, cannot be restarted.
+ *
+ * Always make sure that the whole iteration is consumed (or dropped) to prevent
+ * protocol desynchronization issues.
  *
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */
-abstract class MultiBulkResponse implements \Iterator, \Countable, ResponseObjectInterface
+abstract class MultiBulkResponse implements Iterator, Countable, ResponseObjectInterface
 {
-    protected $position;
     protected $current;
-    protected $replySize;
+    protected $position;
+    protected $size;
 
     /**
      * {@inheritdoc}
@@ -54,7 +62,7 @@ abstract class MultiBulkResponse implements \Iterator, \Countable, ResponseObjec
      */
     public function next()
     {
-        if (++$this->position < $this->replySize) {
+        if (++$this->position < $this->size) {
             $this->current = $this->getValue();
         }
 
@@ -66,21 +74,21 @@ abstract class MultiBulkResponse implements \Iterator, \Countable, ResponseObjec
      */
     public function valid()
     {
-        return $this->position < $this->replySize;
+        return $this->position < $this->size;
     }
 
     /**
-     * Returns the number of items of the whole multibulk reply.
+     * Returns the number of items comprising the whole multibulk response.
      *
-     * This method should be used to get the size of the current multibulk
-     * reply without using iterator_count, which actually consumes the
-     * iterator to calculate the size (rewinding is not supported).
+     * This method should be used instead of iterator_count() to get the size of
+     * the current multibulk response since the former consumes the iteration to
+     * count the number of elements, but our iterators do not support rewinding.
      *
      * @return int
      */
     public function count()
     {
-        return $this->replySize;
+        return $this->size;
     }
 
     /**

+ 10 - 11
lib/Predis/Iterator/MultiBulkResponseSimple.php

@@ -14,7 +14,7 @@ namespace Predis\Iterator;
 use Predis\Connection\SingleConnectionInterface;
 
 /**
- * Streams a multibulk reply.
+ * Streamable multibulk response.
  *
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */
@@ -29,9 +29,9 @@ class MultiBulkResponseSimple extends MultiBulkResponse
     public function __construct(SingleConnectionInterface $connection, $size)
     {
         $this->connection = $connection;
+        $this->size = $size;
         $this->position = 0;
-        $this->current = $size > 0 ? $this->getValue() : null;
-        $this->replySize = $size;
+        $this->current  = $size > 0 ? $this->getValue() : null;
     }
 
     /**
@@ -41,20 +41,19 @@ class MultiBulkResponseSimple extends MultiBulkResponse
      */
     public function __destruct()
     {
-        $this->sync(true);
+        $this->drop(true);
     }
 
     /**
-     * Synchronizes the client with the queued elements that have not been
-     * read from the connection by consuming the rest of the multibulk reply,
-     * or simply by dropping the connection.
+     * Drop queued elements that have not been read from the connection either
+     * by consuming the rest of the multibulk response or quickly by closing the
+     * underlying connection.
      *
-     * @param Boolean $drop True to synchronize the client by dropping the connection.
-     *                      False to synchronize the client by consuming the multibulk reply.
+     * @param bool $disconnect Consume the iterator or drop the connection.
      */
-    public function sync($drop = false)
+    public function drop($disconnect = false)
     {
-        if ($drop == true) {
+        if ($disconnect) {
             if ($this->valid()) {
                 $this->position = $this->replySize;
                 $this->connection->disconnect();

+ 17 - 11
lib/Predis/Iterator/MultiBulkResponseTuple.php

@@ -11,43 +11,49 @@
 
 namespace Predis\Iterator;
 
+use OuterIterator;
+use RuntimeException;
+use UnexpectedValueException;
+
 /**
- * Abstracts the access to a streamable list of tuples represented
- * as a multibulk reply that alternates keys and values.
+ * Outer iterator consuming streamable multibulk responses by yielding tuples of
+ * keys and values.
+ *
+ * This wrapper is useful for responses to commands such as `HGETALL` that can
+ * be iterater as $key => $value pairs.
  *
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */
-class MultiBulkResponseTuple extends MultiBulkResponse implements \OuterIterator
+class MultiBulkResponseTuple extends MultiBulkResponse implements OuterIterator
 {
     private $iterator;
 
     /**
-     * @param MultiBulkResponseSimple $iterator Multibulk reply iterator.
+     * @param MultiBulkResponseSimple $iterator Inner multibulk response iterator.
      */
     public function __construct(MultiBulkResponseSimple $iterator)
     {
         $this->checkPreconditions($iterator);
 
-        $virtualSize = count($iterator) / 2;
+        $this->size = count($iterator) / 2;
         $this->iterator = $iterator;
         $this->position = $iterator->getPosition();
-        $this->current = $virtualSize > 0 ? $this->getValue() : null;
-        $this->replySize = $virtualSize;
+        $this->current  = $this->size > 0 ? $this->getValue() : null;
     }
 
     /**
      * Checks for valid preconditions.
      *
-     * @param MultiBulkResponseSimple $iterator Multibulk reply iterator.
+     * @param MultiBulkResponseSimple $iterator Inner multibulk response iterator.
      */
     protected function checkPreconditions(MultiBulkResponseSimple $iterator)
     {
         if ($iterator->getPosition() !== 0) {
-            throw new \RuntimeException('Cannot initialize a tuple iterator with an already initiated iterator');
+            throw new RuntimeException('Cannot initialize a tuple iterator with an already initiated iterator');
         }
 
         if (($size = count($iterator)) % 2 !== 0) {
-            throw new \UnexpectedValueException("Invalid reply size for a tuple iterator [$size]");
+            throw new UnexpectedValueException("Invalid response size for a tuple iterator [$size]");
         }
     }
 
@@ -64,7 +70,7 @@ class MultiBulkResponseTuple extends MultiBulkResponse implements \OuterIterator
      */
     public function __destruct()
     {
-        $this->iterator->sync(true);
+        $this->iterator->drop(true);
     }
 
     /**

+ 4 - 4
tests/Predis/Iterator/MultiBulkResponseSimpleTest.php

@@ -66,13 +66,13 @@ class MultiBulkResponseSimpleTest extends StandardTestCase
     /**
      * @group connected
      */
-    public function testSyncWithFalseConsumesReplyFromUnderlyingConnection()
+    public function testDropWithFalseConsumesReplyFromUnderlyingConnection()
     {
         $client = $this->getClient();
         $client->rpush('metavars', 'foo', 'hoge', 'lol');
 
         $iterator = $client->lrange('metavars', 0, -1);
-        $iterator->sync(false);
+        $iterator->drop(false);
 
         $this->assertTrue($client->isConnected());
         $this->assertTrue($client->ping());
@@ -81,13 +81,13 @@ class MultiBulkResponseSimpleTest extends StandardTestCase
     /**
      * @group connected
      */
-    public function testSyncWithTrueDropsUnderlyingConnection()
+    public function testDropWithTrueDropsUnderlyingConnection()
     {
         $client = $this->getClient();
         $client->rpush('metavars', 'foo', 'hoge', 'lol');
 
         $iterator = $client->lrange('metavars', 0, -1);
-        $iterator->sync(true);
+        $iterator->drop(true);
 
         $this->assertFalse($client->isConnected());
         $this->assertTrue($client->ping());

+ 1 - 1
tests/Predis/Iterator/MultiBulkResponseTupleTest.php

@@ -40,7 +40,7 @@ class MultiBulkResponseTupleTest extends StandardTestCase
     /**
      * @group disconnected
      * @expectedException UnexpectedValueException
-     * @expectedExceptionMessage Invalid reply size for a tuple iterator [3]
+     * @expectedExceptionMessage Invalid response size for a tuple iterator [3]
      */
     public function testMultiBulkWithOddSizesAreInvalid()
     {