浏览代码

Merge branch 'v0.9/drop-multibulk-iterators'

Daniele Alessandri 11 年之前
父节点
当前提交
70a84e1d5a

+ 4 - 0
CHANGELOG.md

@@ -3,6 +3,10 @@ v0.9.0 (201x-xx-xx)
 
 - The default server profile for Redis is now `2.8`.
 
+- Dropped support for streamable multibulk responses. Actually we still ship the
+  iterator response classes just in case anyone would want to build custom stuff
+  at a level lower than the client abstraction.
+
 - The `Predis\Option` namespace is now known as `Predis\Configuration` and have
   a fully-reworked `Options` class with the ability to lazily initialize values
   using objects that responds to `__invoke()` (not all the kinds of callables)

+ 0 - 56
examples/MultiBulkReplyIterators.php

@@ -1,56 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-require 'SharedConfigurations.php';
-
-// Operations such as LRANGE, ZRANGE and others can potentially generate replies
-// containing a huge number of items. In some corner cases, such replies might
-// end up exhausting the maximum allowed memory allocated for a PHP process.
-// Multibulk iterators can be handy because they allow you to stream multibulk
-// replies using plain old PHP iterators, making it possible to iterate them with
-// a classic `foreach` loop and avoiding to consume an excessive amount of memory.
-//
-// PS: please note that multibulk iterators are supported only by the standard
-// connection backend class (Predis\Connection\StreamConnection) and not the
-// phpiredis-based one (Predis\Connection\PhpiredisConnection).
-
-// Create a client and force the connection to use iterable multibulk responses.
-$client = new Predis\Client($single_server + array('iterable_multibulk' => true));
-
-// Prepare an hash with some fields and their respective values.
-$client->hmset('metavars', array('foo' => 'bar', 'hoge' => 'piyo', 'lol' => 'wut'));
-
-// By default multibulk iterators iterate over the reply as a list of items...
-foreach ($client->hgetall('metavars') as $index => $item) {
-    echo "[$index] $item\n";
-}
-
-/* OUTPUT:
-[0] foo
-[1] bar
-[2] hoge
-[3] piyo
-[4] lol
-[5] wut
-*/
-
-// ... but certain multibulk replies are better represented as lists of tuples.
-foreach ($client->hgetall('metavars')->asTuple() as $index => $kv) {
-    list($key, $value) = $kv;
-
-    echo "[$index] $key => $value\n";
-}
-
-/* OUTPUT:
-[0] foo => bar
-[1] hoge => piyo
-[2] lol => wut
-*/

+ 1 - 1
lib/Predis/Connection/ComposableStreamConnection.php

@@ -130,6 +130,6 @@ class ComposableStreamConnection extends StreamConnection implements ComposableC
      */
     public function __sleep()
     {
-        return array_diff(array_merge(parent::__sleep(), array('protocol')), array('mbiterable'));
+        return array_merge(parent::__sleep(), array('protocol'));
     }
 }

+ 0 - 1
lib/Predis/Connection/ConnectionParameters.php

@@ -64,7 +64,6 @@ class ConnectionParameters implements ConnectionParametersInterface
             'persistent' => 'self::castBoolean',
             'timeout' => 'self::castFloat',
             'read_write_timeout' => 'self::castFloat',
-            'iterable_multibulk' => 'self::castBoolean',
         );
     }
 

+ 0 - 3
lib/Predis/Connection/PhpiredisConnection.php

@@ -89,9 +89,6 @@ class PhpiredisConnection extends AbstractConnection
      */
     protected function checkParameters(ConnectionParametersInterface $parameters)
     {
-        if (isset($parameters->iterable_multibulk)) {
-            $this->onInvalidOption('iterable_multibulk', $parameters);
-        }
         if (isset($parameters->persistent)) {
             $this->onInvalidOption('persistent', $parameters);
         }

+ 0 - 20
lib/Predis/Connection/PhpiredisStreamConnection.php

@@ -83,18 +83,6 @@ class PhpiredisStreamConnection extends StreamConnection
         }
     }
 
-    /**
-     * {@inheritdoc}
-     */
-    protected function checkParameters(ConnectionParametersInterface $parameters)
-    {
-        if (isset($parameters->iterable_multibulk)) {
-            $this->onInvalidOption('iterable_multibulk', $parameters);
-        }
-
-        return parent::checkParameters($parameters);
-    }
-
     /**
      * Initializes the protocol reader resource.
      */
@@ -178,14 +166,6 @@ class PhpiredisStreamConnection extends StreamConnection
         $this->writeBytes(phpiredis_format_command($cmdargs));
     }
 
-    /**
-     * {@inheritdoc}
-     */
-    public function __sleep()
-    {
-        return array_diff(parent::__sleep(), array('mbiterable'));
-    }
-
     /**
      * {@inheritdoc}
      */

+ 0 - 26
lib/Predis/Connection/StreamConnection.php

@@ -14,8 +14,6 @@ namespace Predis\Connection;
 use Predis\ResponseError;
 use Predis\ResponseQueued;
 use Predis\Command\CommandInterface;
-use Predis\Iterator\MultiBulkResponseSimple;
-
 /**
  * Standard connection to Redis servers implemented on top of PHP's streams.
  * The connection parameters supported by this class are:
@@ -28,24 +26,11 @@ use Predis\Iterator\MultiBulkResponseSimple;
  *  - async_connect: performs the connection asynchronously.
  *  - tcp_nodelay: enables or disables Nagle's algorithm for coalescing.
  *  - persistent: the connection is left intact after a GC collection.
- *  - iterable_multibulk: multibulk replies treated as iterable objects.
  *
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */
 class StreamConnection extends AbstractConnection
 {
-    private $mbiterable;
-
-    /**
-     * {@inheritdoc}
-     */
-    public function __construct(ConnectionParametersInterface $parameters)
-    {
-        $this->mbiterable = (bool) $parameters->iterable_multibulk;
-
-        parent::__construct($parameters);
-    }
-
     /**
      * Disconnects from the server and destroys the underlying resource when
      * PHP's garbage collector kicks in only if the connection has not been
@@ -249,9 +234,6 @@ class StreamConnection extends AbstractConnection
                 if ($count === -1) {
                     return null;
                 }
-                if ($this->mbiterable) {
-                    return new MultiBulkResponseSimple($this, $count);
-                }
 
                 $multibulk = array();
 
@@ -293,12 +275,4 @@ class StreamConnection extends AbstractConnection
 
         $this->writeBytes($buffer);
     }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function __sleep()
-    {
-        return array_merge(parent::__sleep(), array('mbiterable'));
-    }
 }

+ 1 - 33
lib/Predis/Pipeline/MultiExecExecutor.php

@@ -11,7 +11,6 @@
 
 namespace Predis\Pipeline;
 
-use Iterator;
 use SplQueue;
 use Predis\ClientException;
 use Predis\ResponseErrorInterface;
@@ -92,38 +91,7 @@ class MultiExecExecutor implements PipelineExecutorInterface
             throw new ClientException("Invalid number of replies [expected: ".count($commands)." - actual: ".count($responses)."]");
         }
 
-        $consumer = $responses instanceof Iterator ? 'consumeIteratorResponse' : 'consumeArrayResponse';
-
-        return $this->$consumer($commands, $responses);
-    }
-
-    /**
-     * Consumes an iterator response returned by EXEC.
-     *
-     * @param SplQueue $commands Pipelined commands
-     * @param Iterator $responses Responses returned by EXEC.
-     * @return array
-     */
-    protected function consumeIteratorResponse(SplQueue $commands, Iterator $responses)
-    {
-        $values = array();
-
-        foreach ($responses as $response) {
-            $command = $commands->dequeue();
-
-            if ($response instanceof ResponseObjectInterface) {
-                if ($response instanceof Iterator) {
-                    $response = iterator_to_array($response);
-                    $values[] = $command->parseResponse($response);
-                } else {
-                    $values[] = $response;
-                }
-            } else {
-                $values[] = $command->parseResponse($response);
-            }
-        }
-
-        return $values;
+        return $this->consumeArrayResponse($commands, $responses);
     }
 
     /**

+ 1 - 2
lib/Predis/Pipeline/SafeClusterExecutor.php

@@ -59,8 +59,7 @@ class SafeClusterExecutor implements PipelineExecutorInterface
             }
 
             try {
-                $response = $cmdConnection->readResponse($command);
-                $values[$i] = $response instanceof \Iterator ? iterator_to_array($response) : $response;
+                $values[$i] = $cmdConnection->readResponse($command);
             } catch (CommunicationException $exception) {
                 $values[$i] = $exception;
                 $connectionExceptions[$connectionObjectHash] = $exception;

+ 1 - 2
lib/Predis/Pipeline/SafeExecutor.php

@@ -43,8 +43,7 @@ class SafeExecutor implements PipelineExecutorInterface
             $command = $commands->dequeue();
 
             try {
-                $response = $connection->readResponse($command);
-                $values[$i] = $response instanceof \Iterator ? iterator_to_array($response) : $response;
+                $values[$i] = $connection->readResponse($command);
             } catch (CommunicationException $exception) {
                 $toAdd = count($commands) - count($values);
                 $values = array_merge($values, array_fill(0, $toAdd, $exception));

+ 0 - 5
lib/Predis/Pipeline/StandardExecutor.php

@@ -11,7 +11,6 @@
 
 namespace Predis\Pipeline;
 
-use Iterator;
 use SplQueue;
 use Predis\ResponseErrorInterface;
 use Predis\ResponseObjectInterface;
@@ -67,10 +66,6 @@ class StandardExecutor implements PipelineExecutorInterface
             return $this->onResponseError($connection, $response);
         }
 
-        if ($response instanceof Iterator) {
-            return $command->parseResponse(iterator_to_array($response));
-        }
-
         return $response;
     }
 

+ 2 - 7
lib/Predis/Transaction/MultiExecContext.php

@@ -375,10 +375,9 @@ class MultiExecContext implements BasicClientInterface, ExecutableContextInterfa
             break;
         } while ($attempts-- > 0);
 
-        $exec = $reply instanceof \Iterator ? iterator_to_array($reply) : $reply;
         $commands = $this->commands;
+        $size = count($reply);
 
-        $size = count($exec);
         if ($size !== count($commands)) {
             $this->onProtocolError("EXEC returned an unexpected number of replies");
         }
@@ -387,17 +386,13 @@ class MultiExecContext implements BasicClientInterface, ExecutableContextInterfa
         $useExceptions = isset($clientOpts->exceptions) ? $clientOpts->exceptions : true;
 
         for ($i = 0; $i < $size; $i++) {
-            $commandReply = $exec[$i];
+            $commandReply = $reply[$i];
 
             if ($commandReply instanceof ResponseErrorInterface && $useExceptions) {
                 $message = $commandReply->getMessage();
                 throw new ServerException($message);
             }
 
-            if ($commandReply instanceof \Iterator) {
-                $commandReply = iterator_to_array($commandReply);
-            }
-
             $values[$i] = $commands->dequeue()->parseResponse($commandReply);
         }
 

+ 0 - 2
tests/Predis/Connection/ConnectionParametersTest.php

@@ -74,7 +74,6 @@ class ParametersTest extends StandardTestCase
         $overrides = array(
             'port' => 7000,
             'database' => 5,
-            'iterable_multibulk' => false,
             'custom' => 'foobar',
         );
 
@@ -85,7 +84,6 @@ class ParametersTest extends StandardTestCase
         $this->assertEquals($overrides['port'], $parameters->port);
 
         $this->assertEquals($overrides['database'], $parameters->database);
-        $this->assertEquals($overrides['iterable_multibulk'], $parameters->iterable_multibulk);
 
         $this->assertTrue(isset($parameters->custom));
         $this->assertEquals($overrides['custom'], $parameters->custom);

+ 0 - 14
tests/Predis/Connection/StreamConnectionTest.php

@@ -87,20 +87,6 @@ class StreamConnectionTest extends ConnectionTestCase
         $this->assertTrue($connection->isConnected());
     }
 
-    /**
-     * @group connected
-     */
-    public function testReadsMultibulkRepliesAsIterators()
-    {
-        $connection = $this->getConnection($profile, true, array('iterable_multibulk' => true));
-
-        $connection->executeCommand($profile->createCommand('rpush', array('metavars', 'foo', 'hoge', 'lol')));
-        $connection->writeCommand($profile->createCommand('lrange', array('metavars', 0, -1)));
-
-        $this->assertInstanceOf('Predis\Iterator\MultiBulkResponse', $iterator = $connection->read());
-        $this->assertSame(array('foo', 'hoge', 'lol'), iterator_to_array($iterator));
-    }
-
     /**
      * @group connected
      * @expectedException Predis\Protocol\ProtocolException

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

@@ -14,6 +14,9 @@ namespace Predis\Iterator;
 use \PHPUnit_Framework_TestCase as StandardTestCase;
 
 use Predis\Client;
+use Predis\Connection\ComposableStreamConnection;
+use Predis\Connection\ConnectionParameters;
+use Predis\Protocol\Text\TextProtocol;
 
 /**
  * @group realm-iterators
@@ -117,18 +120,22 @@ class MultiBulkResponseSimpleTest extends StandardTestCase
      */
     protected function getClient()
     {
-        $parameters = array(
+        $parameters = new ConnectionParameters(array(
             'host' => REDIS_SERVER_HOST,
             'port' => REDIS_SERVER_PORT,
-            'iterable_multibulk' => true,
             'read_write_timeout' => 2,
-        );
+        ));
 
         $options = array(
             'profile' => REDIS_SERVER_VERSION,
         );
 
-        $client = new Client($parameters, $options);
+        $protocol = new TextProtocol();
+        $protocol->setOption('iterable_multibulk', true);
+
+        $connection = new ComposableStreamConnection($parameters, $protocol);
+
+        $client = new Client($connection, $options);
         $client->connect();
         $client->select(REDIS_SERVER_DBNUM);
         $client->flushdb();

+ 11 - 4
tests/Predis/Iterator/MultiBulkResponseTupleTest.php

@@ -14,6 +14,9 @@ namespace Predis\Iterator;
 use \PHPUnit_Framework_TestCase as StandardTestCase;
 
 use Predis\Client;
+use Predis\Connection\ComposableStreamConnection;
+use Predis\Connection\ConnectionParameters;
+use Predis\Protocol\Text\TextProtocol;
 
 /**
  * @group realm-iterators
@@ -103,18 +106,22 @@ class MultiBulkResponseTupleTest extends StandardTestCase
      */
     protected function getClient()
     {
-        $parameters = array(
+        $parameters = new ConnectionParameters(array(
             'host' => REDIS_SERVER_HOST,
             'port' => REDIS_SERVER_PORT,
-            'iterable_multibulk' => true,
             'read_write_timeout' => 2,
-        );
+        ));
 
         $options = array(
             'profile' => REDIS_SERVER_VERSION,
         );
 
-        $client = new Client($parameters, $options);
+        $protocol = new TextProtocol();
+        $protocol->setOption('iterable_multibulk', true);
+
+        $connection = new ComposableStreamConnection($parameters, $protocol);
+
+        $client = new Client($connection, $options);
         $client->connect();
         $client->select(REDIS_SERVER_DBNUM);
         $client->flushdb();

+ 0 - 34
tests/Predis/Pipeline/MultiExecExecutorTest.php

@@ -13,20 +13,12 @@ namespace Predis\Pipeline;
 
 use \PHPUnit_Framework_TestCase as StandardTestCase;
 
-use ArrayIterator;
 use SplQueue;
 use Predis\ResponseError;
 use Predis\ResponseObjectInterface;
 use Predis\ResponseQueued;
 use Predis\Profile\ServerProfile;
 
-/**
- *
- */
-class ResponseIteratorStub extends ArrayIterator implements ResponseObjectInterface
-{
-}
-
 /**
  *
  */
@@ -57,32 +49,6 @@ class MultiExecExecutorTest extends StandardTestCase
         $this->assertSame(array(true, true, true), $replies);
     }
 
-    /**
-     * @group disconnected
-     */
-    public function testExecutorWithSingleConnectionReturningIterator()
-    {
-        $executor = new MultiExecExecutor();
-        $pipeline = $this->getCommandsQueue();
-        $queued = new ResponseQueued();
-        $execResponse = new ResponseIteratorStub(array('PONG', 'PONG', 'PONG'));
-
-        $connection = $this->getMock('Predis\Connection\SingleConnectionInterface');
-        $connection->expects($this->exactly(2))
-                   ->method('executeCommand')
-                   ->will($this->onConsecutiveCalls(true, $execResponse));
-        $connection->expects($this->exactly(3))
-                   ->method('writeCommand');
-        $connection->expects($this->at(3))
-                   ->method('readResponse')
-                   ->will($this->onConsecutiveCalls($queued, $queued, $queued));
-
-        $replies = $executor->execute($connection, $pipeline);
-
-        $this->assertTrue($pipeline->isEmpty());
-        $this->assertSame(array(true, true, true), $replies);
-    }
-
     /**
      * @group disconnected
      * @expectedException Predis\ClientException