mirror of
https://github.com/predis/predis.git
synced 2026-08-31 12:43:31 +00:00
Switch to next slave on -LOADING error response.
This prevents an early failure of the command execution on the client when one slave gets back online but is still loading the dataset from disk (when this happens, Redis returns the -LOADING error response). This commit fixes #280.
This commit is contained in:
@@ -19,6 +19,7 @@ use Predis\Connection\FactoryInterface;
|
||||
use Predis\Connection\NodeConnectionInterface;
|
||||
use Predis\Replication\MissingMasterException;
|
||||
use Predis\Replication\ReplicationStrategy;
|
||||
use Predis\Response\ErrorInterface as ResponseErrorInterface;
|
||||
|
||||
/**
|
||||
* Aggregate connection handling replication of Redis nodes configured in a
|
||||
@@ -431,7 +432,12 @@ class MasterSlaveReplication implements ReplicationInterface
|
||||
{
|
||||
RETRY_COMMAND: {
|
||||
try {
|
||||
$response = $this->getConnection($command)->$method($command);
|
||||
$connection = $this->getConnection($command);
|
||||
$response = $connection->$method($command);
|
||||
|
||||
if ($response instanceof ResponseErrorInterface && $response->getErrorType() === 'LOADING') {
|
||||
throw new ConnectionException($connection, "Redis is loading the dataset in memory [$connection]");
|
||||
}
|
||||
} catch (ConnectionException $exception) {
|
||||
$connection = $exception->getConnection();
|
||||
$connection->disconnect();
|
||||
|
||||
@@ -15,6 +15,7 @@ use Predis\Connection;
|
||||
use Predis\Command;
|
||||
use Predis\Profile;
|
||||
use Predis\Replication\ReplicationStrategy;
|
||||
use Predis\Response;
|
||||
use PredisTestCase;
|
||||
|
||||
/**
|
||||
@@ -682,6 +683,50 @@ class MasterSlaveReplicationTest extends PredisTestCase
|
||||
$replication->executeCommand($cmdSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testDiscardsSlaveWhenRespondsLOADINGAndExecutesReadOnlyCommandOnNextSlave()
|
||||
{
|
||||
$master = $this->getMockConnection('tcp://host1?alias=master');
|
||||
$master->expects($this->never())
|
||||
->method('executeCommand');
|
||||
|
||||
$slave1 = $this->getMockConnection('tcp://host2?alias=slave1');
|
||||
$slave1->expects($this->once())
|
||||
->method('executeCommand')
|
||||
->with($this->isRedisCommand(
|
||||
'EXISTS', array('key')
|
||||
))
|
||||
->will($this->returnValue(
|
||||
new Response\Error('LOADING')
|
||||
));
|
||||
|
||||
$slave2 = $this->getMockConnection('tcp://host3?alias=slave2');
|
||||
$slave2->expects($this->once())
|
||||
->method('executeCommand')
|
||||
->with($this->isRedisCommand(
|
||||
'EXISTS', array('key')
|
||||
))
|
||||
->will($this->returnValue(1));
|
||||
|
||||
$replication = new MasterSlaveReplication();
|
||||
|
||||
$replication->add($master);
|
||||
$replication->add($slave1);
|
||||
$replication->add($slave2);
|
||||
|
||||
$replication->switchTo($slave1);
|
||||
|
||||
$response = $replication->executeCommand(
|
||||
Command\RawCommand::create('exists', 'key')
|
||||
);
|
||||
|
||||
$this->assertSame(1, $response);
|
||||
$this->assertNull($replication->getConnectionById('slave1'));
|
||||
$this->assertSame($slave2, $replication->getConnectionById('slave2'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
* @expectedException \Predis\Connection\ConnectionException
|
||||
|
||||
Reference in New Issue
Block a user