Implement ROLE for proper redis-sentinel support.

Once the client discovers the address of the master or a slave instance,
it must connect to that node and issue a ROLE command to verify that its
role still matches what the client got from the sentinel server.
This commit is contained in:
Daniele Alessandri
2016-05-10 19:10:05 +02:00
parent 0ec9f3351f
commit f8b3f18abf
2 changed files with 49 additions and 1 deletions
@@ -11,6 +11,7 @@
namespace Predis\Connection\Aggregate;
use Predis\CommunicationException;
use Predis\Command\CommandInterface;
use Predis\Command\RawCommand;
use Predis\Connection\ConnectionException;
@@ -19,6 +20,7 @@ use Predis\Connection\FactoryInterface as ConnectionFactoryInterface;
use Predis\Connection\NodeConnectionInterface;
use Predis\Connection\Parameters;
use Predis\Replication\ReplicationStrategy;
use Predis\Replication\RoleException;
use Predis\Response\ErrorInterface as ErrorResponseInterface;
use Predis\Response\ServerException;
@@ -324,6 +326,28 @@ class SentinelReplication extends MasterSlaveReplication
}
}
/**
* {@inheritdoc}
*/
public function getConnection(CommandInterface $command)
{
$connection = parent::getConnection($command);
if (!$connection->isConnected()) {
$role = $connection->executeCommand(RawCommand::create('ROLE'));
if ($connection === $this->master && $role[0] !== 'master') {
throw new RoleException($connection, "Expected master but got $role[0] [$connection]");
}
if ($connection !== $this->master && $role[0] !== 'slave') {
throw new RoleException($connection, "Expected slave but got $role[0] [$connection]");
}
}
return $connection;
}
/**
* Retries the execution of a command upon server failure after asking a new
* configuration to one of the sentinels.
@@ -340,7 +364,7 @@ class SentinelReplication extends MasterSlaveReplication
SENTINEL_RETRY: {
try {
$response = parent::$method($command);
} catch (ConnectionException $exception) {
} catch (CommunicationException $exception) {
if ($retries == $this->retryLimit) {
throw $exception;
}
+24
View File
@@ -0,0 +1,24 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Replication;
use Predis\CommunicationException;
/**
* Exception class that identifies a role mismatch when connecting to node
* managed by redis-sentinel.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class RoleException extends CommunicationException
{
}