diff --git a/lib/Predis/Cluster/PredisClusterHashStrategy.php b/lib/Predis/Cluster/PredisClusterHashStrategy.php index 50b3acc2..92aad88b 100644 --- a/lib/Predis/Cluster/PredisClusterHashStrategy.php +++ b/lib/Predis/Cluster/PredisClusterHashStrategy.php @@ -13,6 +13,7 @@ namespace Predis\Cluster; use Predis\Cluster\Hash\HashGeneratorInterface; use Predis\Command\CommandInterface; +use Predis\Command\ScriptedCommand; /** * Default class used by Predis for client-side sharding to calculate @@ -146,6 +147,10 @@ class PredisClusterHashStrategy implements CommandHashStrategyInterface 'HSET' => $keyIsFirstArgument, 'HSETNX' => $keyIsFirstArgument, 'HVALS' => $keyIsFirstArgument, + + /* scripting */ + 'EVAL' => array($this, 'getKeyFromScriptingCommands'), + 'EVALSHA' => array($this, 'getKeyFromScriptingCommands'), ); } @@ -281,6 +286,23 @@ class PredisClusterHashStrategy implements CommandHashStrategyInterface } } + /** + * Extracts the key from EVAL and EVALSHA commands. + * + * @param CommandInterface $command Command instance. + * @return string + */ + protected function getKeyFromScriptingCommands(CommandInterface $command) + { + $keys = $command instanceof ScriptedCommand + ? $command->getKeys() + : array_slice($args = $command->getArguments(), 2, $args[1]); + + if ($keys && $this->checkSameHashForKeys($keys)) { + return $keys[0]; + } + } + /** * {@inheritdoc} */ diff --git a/tests/Predis/Cluster/PredisClusterHashStrategyTest.php b/tests/Predis/Cluster/PredisClusterHashStrategyTest.php index acf690f6..0ff758ac 100644 --- a/tests/Predis/Cluster/PredisClusterHashStrategyTest.php +++ b/tests/Predis/Cluster/PredisClusterHashStrategyTest.php @@ -149,6 +149,41 @@ class PredisClusterHashStrategyTest extends StandardTestCase } } + /** + * @group disconnected + */ + public function testKeysForScriptCommand() + { + $strategy = $this->getHashStrategy(); + $profile = ServerProfile::getDevelopment(); + $arguments = array('%SCRIPT%', 2, '{key}:1', '{key}:2', 'value1', 'value2'); + + foreach ($this->getExpectedCommands('keys-script') as $commandID) { + $command = $profile->createCommand($commandID, $arguments); + $this->assertNotNull($strategy->getHash($command), $commandID); + } + } + + /** + * @group disconnected + */ + public function testKeysForScriptedCommand() + { + $strategy = $this->getHashStrategy(); + $arguments = array('{key}:1', '{key}:2', 'value1', 'value2'); + + $command = $this->getMock('Predis\Command\ScriptedCommand', array('getScript', 'getKeysCount')); + $command->expects($this->once()) + ->method('getScript') + ->will($this->returnValue('return true')); + $command->expects($this->exactly(2)) + ->method('getKeysCount') + ->will($this->returnValue(2)); + $command->setArguments($arguments); + + $this->assertNotNull($strategy->getHash($command), "Scripted Command [{$command->getId()}]"); + } + /** * @group disconnected */ @@ -315,6 +350,10 @@ class PredisClusterHashStrategyTest extends StandardTestCase 'HSET' => 'keys-first', 'HSETNX' => 'keys-first', 'HVALS' => 'keys-first', + + /* scripting */ + 'EVAL' => 'keys-script', + 'EVALSHA' => 'keys-script', ); if (isset($type)) {