浏览代码

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.
Daniele Alessandri 13 年之前
父节点
当前提交
1ac9cc9c71

+ 21 - 0
lib/Predis/Cluster/RedisClusterHashStrategy.php

@@ -134,6 +134,10 @@ class RedisClusterHashStrategy implements CommandHashStrategyInterface
             'HSET'                  => $keyIsFirstArgument,
             'HSET'                  => $keyIsFirstArgument,
             'HSETNX'                => $keyIsFirstArgument,
             'HSETNX'                => $keyIsFirstArgument,
             'HVALS'                 => $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}
      * {@inheritdoc}
      */
      */

+ 1 - 1
lib/Predis/Connection/RedisCluster.php

@@ -280,7 +280,7 @@ class RedisCluster implements ClusterConnectionInterface, \IteratorAggregate, \C
      */
      */
     public function getCommandHashStrategy()
     public function getCommandHashStrategy()
     {
     {
-        return $this->cmdHasher;
+        return $this->strategy;
     }
     }
 
 
     /**
     /**

+ 39 - 0
tests/Predis/Cluster/RedisClusterHashStrategyTest.php

@@ -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
      * @group disconnected
      */
      */
@@ -312,6 +347,10 @@ class RedisClusterHashStrategyTest extends StandardTestCase
             'HSET'                  => 'keys-first',
             'HSET'                  => 'keys-first',
             'HSETNX'                => 'keys-first',
             'HSETNX'                => 'keys-first',
             'HVALS'                 => 'keys-first',
             'HVALS'                 => 'keys-first',
+
+            /* scripting */
+            'EVAL'                  => 'keys-script',
+            'EVALSHA'               => 'keys-script',
         );
         );
 
 
         if (isset($type)) {
         if (isset($type)) {