Bläddra i källkod

Implement IteratorAggregate interface for Client.

Now it is possible to iterate over traversable aggregate connections
and get a key/value pair of $connectionId => $clientInstance for each
node.
Daniele Alessandri 8 år sedan
förälder
incheckning
ecab7e4642
3 ändrade filer med 99 tillägg och 1 borttagningar
  1. 4 0
      CHANGELOG.md
  2. 20 1
      src/Client.php
  3. 75 0
      tests/Predis/ClientTest.php

+ 4 - 0
CHANGELOG.md

@@ -39,6 +39,10 @@ v1.1.0 (2016-0x-xx)
   use the `tls` or `rediss` schemes in connection parameters along with specific
   use the `tls` or `rediss` schemes in connection parameters along with specific
   options via the `ssl` parameter (see http://php.net/manual/context.ssl.php).
   options via the `ssl` parameter (see http://php.net/manual/context.ssl.php).
 
 
+- Implemented the `IteratorAggregate` interface for `Predis\Client` so now it is
+  possible to iterate over traversable aggregate connections and get a key/value
+  pair consisting of $connectionID => $clientInstance for each node.
+
 - Iterating over `Predis\Connection\Aggregate\RedisCluster` now returns all the
 - Iterating over `Predis\Connection\Aggregate\RedisCluster` now returns all the
   connections currently mapped in the slots map instead of just the connections
   connections currently mapped in the slots map instead of just the connections
   initialized in the pool. When the slots map is retrieved from Redis (which is
   initialized in the pool. When the slots map is retrieved from Redis (which is

+ 20 - 1
src/Client.php

@@ -38,7 +38,7 @@ use Predis\Transaction\MultiExec as MultiExecTransaction;
  *
  *
  * @author Daniele Alessandri <suppakilla@gmail.com>
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */
  */
-class Client implements ClientInterface
+class Client implements ClientInterface, \IteratorAggregate
 {
 {
     const VERSION = '1.1.0-dev';
     const VERSION = '1.1.0-dev';
 
 
@@ -525,4 +525,23 @@ class Client implements ClientInterface
     {
     {
         return new MonitorConsumer($this);
         return new MonitorConsumer($this);
     }
     }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getIterator()
+    {
+        $clients = array();
+        $connection = $this->getConnection();
+
+        if (!$connection instanceof \Traversable) {
+            throw new ClientException('The underlying connection is not traversable');
+        }
+
+        foreach ($connection as $node) {
+            $clients[(string) $node] = new static($node, $this->getOptions());
+        }
+
+        return new \ArrayIterator($clients);
+    }
 }
 }

+ 75 - 0
tests/Predis/ClientTest.php

@@ -815,6 +815,55 @@ class ClientTest extends PredisTestCase
         $this->assertTrue($client->executeCommand($command));
         $this->assertTrue($client->executeCommand($command));
     }
     }
 
 
+    /**
+     * @group disconnected
+     */
+    public function testGetIteratorWithTraversableConnections()
+    {
+        $connection1 = $this->getMockConnection('tcp://127.0.0.1:6381');
+        $connection2 = $this->getMockConnection('tcp://127.0.0.1:6382');
+        $connection3 = $this->getMockConnection('tcp://127.0.0.1:6383');
+
+        $aggregate = new \Predis\Connection\Aggregate\PredisCluster();
+
+        $aggregate->add($connection1);
+        $aggregate->add($connection2);
+        $aggregate->add($connection3);
+
+        $client = new Client($aggregate);
+
+        $iterator = $client->getIterator();
+
+        $this->assertInstanceOf('\Predis\Client', $nodeClient = $iterator->current());
+        $this->assertSame($connection1, $nodeClient->getConnection());
+        $this->assertSame('127.0.0.1:6381', $iterator->key());
+
+        $iterator->next();
+
+        $this->assertInstanceOf('\Predis\Client', $nodeClient = $iterator->current());
+        $this->assertSame($connection2, $nodeClient->getConnection());
+        $this->assertSame('127.0.0.1:6382', $iterator->key());
+
+        $iterator->next();
+
+        $this->assertInstanceOf('\Predis\Client', $nodeClient = $iterator->current());
+        $this->assertSame($connection3, $nodeClient->getConnection());
+        $this->assertSame('127.0.0.1:6383', $iterator->key());
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException \Predis\ClientException
+     * @expectedExceptionMessage The underlying connection is not traversable
+     */
+    public function testGetIteratorWithNonTraversableConnectionThrowsException()
+    {
+        $connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
+        $client = new Client($connection);
+
+        $client->getIterator();
+    }
+
     // ******************************************************************** //
     // ******************************************************************** //
     // ---- HELPER METHODS ------------------------------------------------ //
     // ---- HELPER METHODS ------------------------------------------------ //
     // ******************************************************************** //
     // ******************************************************************** //
@@ -843,4 +892,30 @@ class ClientTest extends PredisTestCase
 
 
         return $uriString;
         return $uriString;
     }
     }
+
+    /**
+     * Returns a base mocked connection from Predis\Connection\NodeConnectionInterface.
+     *
+     * @param mixed $parameters Optional parameters.
+     *
+     * @return mixed
+     */
+    protected function getMockConnection($parameters = null)
+    {
+        $connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
+
+        if ($parameters) {
+            $parameters = \Predis\Connection\Parameters::create($parameters);
+            $hash = "{$parameters->host}:{$parameters->port}";
+
+            $connection->expects($this->any())
+                       ->method('getParameters')
+                       ->will($this->returnValue($parameters));
+            $connection->expects($this->any())
+                       ->method('__toString')
+                       ->will($this->returnValue($hash));
+        }
+
+        return $connection;
+    }
 }
 }