Browse Source

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 years ago
parent
commit
ecab7e4642
3 changed files with 99 additions and 1 deletions
  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
   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
   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

+ 20 - 1
src/Client.php

@@ -38,7 +38,7 @@ use Predis\Transaction\MultiExec as MultiExecTransaction;
  *
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */
-class Client implements ClientInterface
+class Client implements ClientInterface, \IteratorAggregate
 {
     const VERSION = '1.1.0-dev';
 
@@ -525,4 +525,23 @@ class Client implements ClientInterface
     {
         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));
     }
 
+    /**
+     * @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 ------------------------------------------------ //
     // ******************************************************************** //
@@ -843,4 +892,30 @@ class ClientTest extends PredisTestCase
 
         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;
+    }
 }