Przeglądaj źródła

Replace "getClientFor()" with "on()" in Client.

This new method acts exactly like "getClientFor()" by returning a new
client instance for the specified node unless a callback is passed as
the second argument, in this case the callback is invoked and the new
client instance is passed to it. The value returned by the callback
is used as the return value of the "on()" method.
Daniele Alessandri 8 lat temu
rodzic
commit
ee7104d2e5

+ 7 - 0
CHANGELOG.md

@@ -35,6 +35,13 @@ v2.0.0 (201x-xx-xx)
   in the `Predis\Command\Redis` when the internal class map does not contain a
   class associated.
 
+- The method `Predis\Client::getClientFor($connectionID)` has been replaced by
+  `Predis\Client::on($connectionID, $callable = null)`. This new method returns
+  a new client instance for the specified node just like before when the second
+  argument is omitted, otherwise the callback is invoked and the new client is
+  passed to it. The value returned by the callback is used as the return value
+  of the "on()" method.
+
 - Changed the signature for the constructor of `Predis\Command\RawCommand`.
 
 - The `Predis\Connection\Aggregate` namespace has been split into two separate

+ 2 - 2
examples/custom_cluster_distributor.php

@@ -104,8 +104,8 @@ for ($i = 0; $i < 100; ++$i) {
     $client->get("key:$i");
 }
 
-$server1 = $client->getClientFor('first')->info();
-$server2 = $client->getClientFor('second')->info();
+$server1 = $client->on('first')->info();
+$server2 = $client->on('second')->info();
 
 if (isset($server1['Keyspace'], $server2['Keyspace'])) {
     $server1 = $server1['Keyspace'];

+ 20 - 9
src/Client.php

@@ -195,23 +195,34 @@ class Client implements ClientInterface, \IteratorAggregate
     }
 
     /**
-     * Creates a new client instance for the specified connection ID or alias,
-     * only when working with an aggregate connection (cluster, replication).
-     * The new client instances uses the same options of the original one.
+     * Creates a new client from the specified connection ID / alias.
      *
-     * @param string $connectionID Identifier of a connection.
+     * The new client instances inherites the same options of the original one.
+     * When no callable object is supplied, this method returns the new client.
+     * When a callable object is supplied, the new client is passed as its sole
+     * argument and its return value is returned by this method to the caller.
      *
-     * @throws \InvalidArgumentException
+     * NOTE: This method works only when the client is configured to work with
+     * aggregate connections (cluster, replication).
+     *
+     * @param string        $connectionID Identifier of a connection.
+     * @param callable|null $callable     Optional callable object.
      *
-     * @return Client
+     * @return ClientInterface|mixed
      */
-    public function getClientFor($connectionID)
+    public function on($connectionID, $callable = null)
     {
         if (!$connection = $this->getConnectionById($connectionID)) {
-            throw new \InvalidArgumentException("Invalid connection ID: $connectionID.");
+            throw new \InvalidArgumentException("Invalid connection ID: `$connectionID`");
         }
 
-        return new static($connection, $this->options);
+        $client = new static($connection, $this->getOptions());
+
+        if ($callable) {
+            return call_user_func($callable, $client);
+        } else {
+            return $client;
+        }
     }
 
     /**

+ 52 - 4
tests/Predis/ClientTest.php

@@ -659,7 +659,7 @@ class ClientTest extends PredisTestCase
     /**
      * @group disconnected
      */
-    public function testCreateClientWithConnectionFromAggregateConnection()
+    public function testOnMethodCreatesClientWithConnectionFromAggregateConnection()
     {
         $client = new Client(array('tcp://host1?alias=node01', 'tcp://host2?alias=node02'), array('prefix' => 'pfx:', 'cluster' => 'predis'));
 
@@ -667,7 +667,7 @@ class ClientTest extends PredisTestCase
         $this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $node01 = $client->getConnectionById('node01'));
         $this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $node02 = $client->getConnectionById('node02'));
 
-        $clientNode02 = $client->getClientFor('node02');
+        $clientNode02 = $client->on('node02');
 
         $this->assertInstanceOf('Predis\Client', $clientNode02);
         $this->assertSame($node02, $clientNode02->getConnection());
@@ -677,12 +677,60 @@ class ClientTest extends PredisTestCase
     /**
      * @group disconnected
      */
-    public function testGetClientForReturnsInstanceOfSubclass()
+    public function testOnMethodReturnsInstanceOfSubclass()
     {
         $nodes = array('tcp://host1?alias=node01', 'tcp://host2?alias=node02');
         $client = $this->getMock('Predis\Client', array('dummy'), array($nodes, array('cluster' => 'predis')), 'SubclassedClient');
 
-        $this->assertInstanceOf('SubclassedClient', $client->getClientFor('node02'));
+        $this->assertInstanceOf('SubclassedClient', $client->on('node02'));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testOnMethodInvokesCallableInSecondArgumentAndReturnsItsReturnValue()
+    {
+        $test = $this;
+        $client = new Client(array('tcp://host1?alias=node01', 'tcp://host2?alias=node02'), array('cluster' => 'predis'));
+
+        $callable = $this->getMock('stdClass', array('__invoke'));
+        $callable->expects($this->once())
+                 ->method('__invoke')
+                 ->with($this->callback(function ($clientNode) use ($test, $client) {
+                     $test->isInstanceOf('Predis\ClientInterface', $clientNode);
+                     $test->assertNotSame($client, $clientNode);
+                     $test->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection = $clientNode->getConnection());
+                     $test->assertSame('node02', $connection->getParameters()->alias);
+
+                     return true;
+                 }))
+                 ->will($this->returnValue('value'));
+
+        $this->assertSame('value', $client->on('node02', $callable));
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException \Predis\NotSupportedException
+     * @expectedExceptionMessage Retrieving connections by ID is supported only by aggregate connections
+     */
+    public function testOnMethodThrowsExceptionWithNodeConnection()
+    {
+        $client = new Client('tcp://127.0.0.1?alias=node01');
+
+        $client->on('node01');
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException \InvalidArgumentException
+     * @expectedExceptionMessage Invalid connection ID: `nodeXX`
+     */
+    public function testOnMethodThrowsExceptionWithUnknownConnectionID()
+    {
+        $client = new Client(array('tcp://host1?alias=node01', 'tcp://host2?alias=node02'), array('cluster' => 'predis'));
+
+        $client->on('nodeXX');
     }
 
     /**