From ee7104d2e576d3cbe8e76830b18ec7d4f457a382 Mon Sep 17 00:00:00 2001 From: Daniele Alessandri Date: Tue, 7 Jun 2016 18:58:21 +0200 Subject: [PATCH] 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. --- CHANGELOG.md | 7 ++++ examples/custom_cluster_distributor.php | 4 +- src/Client.php | 29 +++++++++---- tests/Predis/ClientTest.php | 56 +++++++++++++++++++++++-- 4 files changed, 81 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8481bfce..4436a44f 100644 --- a/CHANGELOG.md +++ b/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 diff --git a/examples/custom_cluster_distributor.php b/examples/custom_cluster_distributor.php index 102ca906..a728f7c9 100644 --- a/examples/custom_cluster_distributor.php +++ b/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']; diff --git a/src/Client.php b/src/Client.php index 5ce98f44..883f774e 100644 --- a/src/Client.php +++ b/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). * - * @return Client + * @param string $connectionID Identifier of a connection. + * @param callable|null $callable Optional callable object. + * + * @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; + } } /** diff --git a/tests/Predis/ClientTest.php b/tests/Predis/ClientTest.php index ff8cd67b..29dc6f45 100644 --- a/tests/Predis/ClientTest.php +++ b/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'); } /**