Browse Source

Improve handling of -MOVED and -ASK responses.

This change improves code reusing and simplifies the internals of
our redis-cluster connection backend.
Daniele Alessandri 11 years ago
parent
commit
5f81bfcde3
1 changed files with 57 additions and 42 deletions
  1. 57 42
      lib/Predis/Connection/RedisCluster.php

+ 57 - 42
lib/Predis/Connection/RedisCluster.php

@@ -19,7 +19,6 @@ use Predis\NotSupportedException;
 use Predis\Cluster\RedisStrategy as RedisClusterStrategy;
 use Predis\Command\CommandInterface;
 use Predis\Command\RawCommand;
-use Predis\Protocol\ProtocolException;
 use Predis\Response\ErrorInterface as ErrorResponseInterface;
 
 /**
@@ -257,6 +256,26 @@ class RedisCluster implements ClusterConnectionInterface, IteratorAggregate, Cou
         return $nodes[$index];
     }
 
+    /**
+     * Creates a new connection instance from the given connection ID.
+     *
+     * @param  string                    $connectionID Identifier for the connection.
+     * @return SingleConnectionInterface
+     */
+    protected function createConnection($connectionID)
+    {
+        $host = explode(':', $connectionID, 2);
+
+        $parameters = array_merge($this->defaultParameters, array(
+            'host' => $host[0],
+            'port' => $host[1],
+        ));
+
+        $connection = $this->connections->create($parameters);
+
+        return $connection;
+    }
+
     /**
      * {@inheritdoc}
      */
@@ -298,13 +317,7 @@ class RedisCluster implements ClusterConnectionInterface, IteratorAggregate, Cou
         $connectionID = $this->guessNode($slot);
 
         if (!$connection = $this->getConnectionById($connectionID)) {
-            $host = explode(':', $connectionID, 2);
-            $parameters = array_merge($this->defaultParameters, array(
-                'host' => $host[0],
-                'port' => $host[1],
-            ));
-
-            $connection = $this->connections->create($parameters);
+            $connection = $this->createConnection($connectionID);
             $this->pool[$connectionID] = $connection;
         }
 
@@ -347,7 +360,7 @@ class RedisCluster implements ClusterConnectionInterface, IteratorAggregate, Cou
     }
 
     /**
-     * Handles -ERR responses from Redis.
+     * Handles -ERR responses returned by Redis.
      *
      * @param  CommandInterface       $command Command that generated the -ERR response.
      * @param  ErrorResponseInterface $error   Redis error response object.
@@ -359,8 +372,10 @@ class RedisCluster implements ClusterConnectionInterface, IteratorAggregate, Cou
 
         switch ($details[0]) {
             case 'MOVED':
+                return $this->onMovedResponse($command, $details[1]);
+
             case 'ASK':
-                return $this->onMoveRequest($command, $details[0], $details[1]);
+                return $this->onAskResponse($command, $details[1]);
 
             default:
                 return $error;
@@ -368,51 +383,51 @@ class RedisCluster implements ClusterConnectionInterface, IteratorAggregate, Cou
     }
 
     /**
-     * Handles -MOVED and -ASK responses by re-executing the command on the node
-     * specified by the Redis response.
+     * Handles -MOVED responses by executing again the command against the node
+     * indicated by the Redis response.
      *
-     * @param  CommandInterface $command Command that generated the -MOVE or -ASK response.
-     * @param  string           $request Type of request (either 'MOVED' or 'ASK').
-     * @param  string           $details Parameters of the MOVED/ASK request.
+     * @param  CommandInterface $command Command that generated the -MOVED response.
+     * @param  string           $details Parameters of the -MOVED response.
      * @return mixed
      */
-    protected function onMoveRequest(CommandInterface $command, $request, $details)
+    protected function onMovedResponse(CommandInterface $command, $details)
     {
-        list($slot, $host) = explode(' ', $details, 2);
-        $connection = $this->getConnectionById($host);
+        list($slot, $connectionID) = explode(' ', $details, 2);
 
-        if (!$connection) {
-            $host = explode(':', $host, 2);
-            $parameters = array_merge($this->defaultParameters, array(
-                'host' => $host[0],
-                'port' => $host[1],
-            ));
+        if (!$connection = $this->getConnectionById($connectionID)) {
+            $connection = $this->createConnection($connectionID);
+        }
 
-            $connection = $this->connections->create($parameters);
+        if ($this->askClusterNodes) {
+            $this->askClusterNodes();
         }
 
-        switch ($request) {
-            case 'MOVED':
-                if ($this->askClusterNodes) {
-                    $this->askClusterNodes();
-                }
+        $this->move($connection, $slot);
+        $response = $this->executeCommand($command);
 
-                $this->move($connection, $slot);
-                $response = $this->executeCommand($command);
+        return $response;
+    }
 
-                return $response;
+    /**
+     * Handles -ASK responses by executing again the command against the node
+     * indicated by the Redis response.
+     *
+     * @param  CommandInterface $command Command that generated the -ASK response.
+     * @param  string           $details Parameters of the -ASK response.
+     * @return mixed
+     */
+    protected function onAskResponse(CommandInterface $command, $details)
+    {
+        list($slot, $connectionID) = explode(' ', $details, 2);
 
-            case 'ASK':
-                $connection->executeCommand(RawCommand::create('ASKING'));
-                $response = $connection->executeCommand($command);
+        if (!$connection = $this->getConnectionById($connectionID)) {
+            $connection = $this->createConnection($connectionID);
+        }
 
-                return $response;
+        $connection->executeCommand(RawCommand::create('ASKING'));
+        $response = $connection->executeCommand($command);
 
-            default:
-                throw new ProtocolException(
-                    "Unexpected request type for a move request: $request."
-                );
-        }
+        return $response;
     }
 
     /**