Support EVAL and EVALSHA with redis-cluster.

We extract the keys from commands using the second argument of EVAL /
EVALSHA which specifies the number of arguments that must be treated
as keys (used to populate the KEYS table in the Lua script) and then
we check if there is only one key since redis-cluster right now does
not support multi-keys requests.

Our scripted command abstraction is also supported.
This commit is contained in:
Daniele Alessandri
2012-08-02 12:08:56 +02:00
parent b2f59a0c63
commit 1ac9cc9c71
3 changed files with 61 additions and 1 deletions
@@ -134,6 +134,10 @@ class RedisClusterHashStrategy implements CommandHashStrategyInterface
'HSET' => $keyIsFirstArgument,
'HSETNX' => $keyIsFirstArgument,
'HVALS' => $keyIsFirstArgument,
/* scripting */
'EVAL' => array($this, 'getKeyFromScriptingCommands'),
'EVALSHA' => array($this, 'getKeyFromScriptingCommands'),
);
}
@@ -234,6 +238,23 @@ class RedisClusterHashStrategy 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 (count($keys) === 1) {
return $keys[0];
}
}
/**
* {@inheritdoc}
*/
+1 -1
View File
@@ -280,7 +280,7 @@ class RedisCluster implements ClusterConnectionInterface, \IteratorAggregate, \C
*/
public function getCommandHashStrategy()
{
return $this->cmdHasher;
return $this->strategy;
}
/**
@@ -159,6 +159,41 @@ class RedisClusterHashStrategyTest extends StandardTestCase
}
}
/**
* @group disconnected
*/
public function testKeysForScriptCommand()
{
$strategy = $this->getHashStrategy();
$profile = ServerProfile::getDevelopment();
$arguments = array('%SCRIPT%', 1, 'key:1', 'value1');
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', 'value1');
$command = $this->getMock('Predis\Command\ScriptedCommand', array('getScript', 'getKeysCount'));
$command->expects($this->once())
->method('getScript')
->will($this->returnValue('return true'));
$command->expects($this->exactly(1))
->method('getKeysCount')
->will($this->returnValue(1));
$command->setArguments($arguments);
$this->assertNotNull($strategy->getHash($command), "Scripted Command [{$command->getId()}]");
}
/**
* @group disconnected
*/
@@ -312,6 +347,10 @@ class RedisClusterHashStrategyTest extends StandardTestCase
'HSET' => 'keys-first',
'HSETNX' => 'keys-first',
'HVALS' => 'keys-first',
/* scripting */
'EVAL' => 'keys-script',
'EVALSHA' => 'keys-script',
);
if (isset($type)) {