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'); } /**