浏览代码

Send ASKING command when redis-cluster returns a -ASK response.

We must always execute ASKING on the connection identified by the -ASK
response before executing the actual command because not doing so will
break the cluster specifications while redis-cluster is performing a
resharding operation.
Daniele Alessandri 11 年之前
父节点
当前提交
5d7f297110
共有 2 个文件被更改,包括 25 次插入4 次删除
  1. 6 2
      lib/Predis/Connection/RedisCluster.php
  2. 19 2
      tests/Predis/Connection/RedisClusterTest.php

+ 6 - 2
lib/Predis/Connection/RedisCluster.php

@@ -15,6 +15,7 @@ use Predis\ClientException;
 use Predis\NotSupportedException;
 use Predis\Cluster;
 use Predis\Command\CommandInterface;
+use Predis\Command\RawCommand;
 use Predis\Response;
 
 /**
@@ -279,10 +280,13 @@ class RedisCluster implements ClusterConnectionInterface, \IteratorAggregate, \C
         switch ($request) {
             case 'MOVED':
                 $this->move($connection, $slot);
-                return $this->executeCommand($command);
+                $response = $this->executeCommand($command);
+                return $response;
 
             case 'ASK':
-                return $connection->executeCommand($command);
+                $connection->executeCommand(RawCommand::create('ASKING'));
+                $response = $connection->executeCommand($command);
+                return $response;
 
             default:
                 throw new ClientException("Unexpected request type for a move request: $request");

+ 19 - 2
tests/Predis/Connection/RedisClusterTest.php

@@ -434,7 +434,10 @@ class RedisClusterTest extends StandardTestCase
                     ->will($this->onConsecutiveCalls($askResponse, 'foobar'));
 
         $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
-        $connection2->expects($this->exactly(1))
+        $connection2->expects($this->at(2))
+                    ->method('executeCommand')
+                    ->with($this->isRedisCommand('ASKING'));
+        $connection2->expects($this->at(3))
                     ->method('executeCommand')
                     ->with($command)
                     ->will($this->returnValue('foobar'));
@@ -471,7 +474,10 @@ class RedisClusterTest extends StandardTestCase
                     ->method('executeCommand');
 
         $connection3 = $this->getMockConnection('tcp://127.0.0.1:6381');
-        $connection3->expects($this->once())
+        $connection3->expects($this->at(0))
+                    ->method('executeCommand')
+                    ->with($this->isRedisCommand('ASKING'));
+        $connection3->expects($this->at(1))
                     ->method('executeCommand')
                     ->with($command)
                     ->will($this->returnValue('foobar'));
@@ -605,6 +611,17 @@ class RedisClusterTest extends StandardTestCase
     // ---- HELPER METHODS ------------------------------------------------ //
     // ******************************************************************** //
 
+    /**
+     * Asserts that two arrays have the same values, even if with different order.
+     *
+     * @param string|CommandInterface $command Expected command or command ID.
+     * @param array $arguments Expected command arguments.
+     */
+    protected function isRedisCommand($command = null, array $arguments = null)
+    {
+        return new \RedisCommandConstraint($command, $arguments);
+    }
+
     /**
      * Returns a base mocked connection from Predis\Connection\SingleConnectionInterface.
      *