mirror of
https://github.com/predis/predis.git
synced 2026-08-20 21:41:49 +00:00
2e76410e65
Password-based authentication for sentinels has been added in Redis 5. Predis was actively ignoring any "password" parameter for sentinels when creating connections to them to avoid issues when this parameter is set in the default "parameters" array passed via client options, as they are applied to **every** connection created by Predis (see #346). We need to find a better way to specify a common password for sentinels to be handled in a different way than the ones for Redis nodes. For now each sentinel node protected by password must have an explicit password set in its parameters list even if this password, by design, is the same for all sentinels. Since we cannot use default "parameters" as explained above but we still need to pass a common value for all sentinels an idea could be using a dedicated client option like we did with "service", but we will see later. In this commit we also explicitly reset any "username" parameter as it would trigger an `AUTH $username $password` but sentinels do not support ACL authentication. Fixes #594.
1275 lines
48 KiB
PHP
1275 lines
48 KiB
PHP
<?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\Connection\Aggregate;
|
|
|
|
use Predis\Command;
|
|
use Predis\Connection;
|
|
use Predis\Replication;
|
|
use Predis\Response;
|
|
use PredisTestCase;
|
|
|
|
/**
|
|
*
|
|
*/
|
|
class SentinelReplicationTest extends PredisTestCase
|
|
{
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException Predis\ClientException
|
|
* @expectedExceptionMessage No sentinel server available for autodiscovery.
|
|
*/
|
|
public function testMethodGetSentinelConnectionThrowsExceptionOnEmptySentinelsPool()
|
|
{
|
|
$replication = $this->getReplicationConnection('svc', array());
|
|
$replication->getSentinelConnection();
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testParametersForSentinelConnectionShouldUsePasswordForAuthentication()
|
|
{
|
|
$replication = $this->getReplicationConnection('svc', array(
|
|
'tcp://127.0.0.1:5381?alias=sentinel1&password=secret',
|
|
));
|
|
|
|
$parameters = $replication->getSentinelConnection()->getParameters()->toArray();
|
|
|
|
$this->assertArraySubset(array('password' => 'secret'), $parameters);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testParametersForSentinelConnectionShouldNotUseDatabaseAndUsername()
|
|
{
|
|
$replication = $this->getReplicationConnection('svc', array(
|
|
'tcp://127.0.0.1:5381?alias=sentinel1&database=1&username=myusername',
|
|
));
|
|
|
|
$parameters = $replication->getSentinelConnection()->getParameters()->toArray();
|
|
|
|
$this->assertArraySubset(array('database' => null, 'username' => null), $parameters);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testParametersForSentinelConnectionHaveDefaultTimeout()
|
|
{
|
|
$replication = $this->getReplicationConnection('svc', array(
|
|
'tcp://127.0.0.1:5381?alias=sentinel',
|
|
));
|
|
|
|
$parameters = $replication->getSentinelConnection()->getParameters()->toArray();
|
|
|
|
$this->assertArrayHasKey('timeout', $parameters);
|
|
$this->assertSame(0.100, $parameters['timeout']);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testParametersForSentinelConnectionCanOverrideDefaultTimeout()
|
|
{
|
|
$replication = $this->getReplicationConnection('svc', array(
|
|
'tcp://127.0.0.1:5381?alias=sentinel&timeout=1',
|
|
));
|
|
|
|
$parameters = $replication->getSentinelConnection()->getParameters()->toArray();
|
|
|
|
$this->assertArrayHasKey('timeout', $parameters);
|
|
$this->assertSame('1', $parameters['timeout']);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testConnectionParametersInstanceForSentinelConnectionIsNotModified()
|
|
{
|
|
$originalParameters = Connection\Parameters::create(
|
|
'tcp://127.0.0.1:5381?alias=sentinel1&database=1&password=secret'
|
|
);
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($originalParameters));
|
|
|
|
$parameters = $replication->getSentinelConnection()->getParameters();
|
|
|
|
$this->assertSame($originalParameters, $parameters);
|
|
$this->assertNotNull($parameters->password);
|
|
$this->assertNotNull($parameters->database);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodGetSentinelConnectionReturnsFirstAvailableSentinel()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
$sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?alias=sentinel2');
|
|
$sentinel3 = $this->getMockSentinelConnection('tcp://127.0.0.1:5383?alias=sentinel3');
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1, $sentinel2, $sentinel3));
|
|
|
|
$this->assertSame($sentinel1, $replication->getSentinelConnection());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodAddAttachesMasterOrSlaveNodesToReplication()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
|
|
$slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?alias=slave2');
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->add($master);
|
|
$replication->add($slave1);
|
|
$replication->add($slave2);
|
|
|
|
$this->assertSame($master, $replication->getConnectionById('master'));
|
|
$this->assertSame($slave1, $replication->getConnectionById('slave1'));
|
|
$this->assertSame($slave2, $replication->getConnectionById('slave2'));
|
|
|
|
$this->assertSame($master, $replication->getMaster());
|
|
$this->assertSame(array($slave1, $slave2), $replication->getSlaves());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodRemoveDismissesMasterOrSlaveNodesFromReplication()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
|
|
$slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?alias=slave2');
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->add($master);
|
|
$replication->add($slave1);
|
|
$replication->add($slave2);
|
|
|
|
$this->assertTrue($replication->remove($slave1));
|
|
$this->assertFalse($replication->remove($sentinel1));
|
|
|
|
$this->assertSame('127.0.0.1:6381', (string) $replication->getMaster());
|
|
$this->assertCount(1, $slaves = $replication->getSlaves());
|
|
$this->assertSame('127.0.0.1:6383', (string) $slaves[0]);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodUpdateSentinelsFetchesSentinelNodes()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
$sentinel1->expects($this->once())
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand(
|
|
'SENTINEL', array('sentinels', 'svc')
|
|
))
|
|
->will($this->returnValue(
|
|
array(
|
|
array(
|
|
'name', '127.0.0.1:5382',
|
|
'ip', '127.0.0.1',
|
|
'port', '5382',
|
|
'runid', 'a113aa7a0d4870a85bb22b4b605fd26eb93ed40e',
|
|
'flags', 'sentinel',
|
|
),
|
|
array(
|
|
'name', '127.0.0.1:5383',
|
|
'ip', '127.0.0.1',
|
|
'port', '5383',
|
|
'runid', 'f53b52d281be5cdd4873700c94846af8dbe47209',
|
|
'flags', 'sentinel',
|
|
),
|
|
)
|
|
));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->updateSentinels();
|
|
|
|
// TODO: sorry for the smell...
|
|
$reflection = new \ReflectionProperty($replication, 'sentinels');
|
|
$reflection->setAccessible(true);
|
|
|
|
$expected = array(
|
|
array('host' => '127.0.0.1', 'port' => '5381'),
|
|
array('host' => '127.0.0.1', 'port' => '5382'),
|
|
array('host' => '127.0.0.1', 'port' => '5383'),
|
|
);
|
|
|
|
$this->assertSame($sentinel1, $replication->getSentinelConnection());
|
|
$this->assertSame($expected, array_intersect_key($expected, $reflection->getValue($replication)));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodUpdateSentinelsRemovesCurrentSentinelAndRetriesNextOneOnFailure()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
$sentinel1->expects($this->once())
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand(
|
|
'SENTINEL', array('sentinels', 'svc')
|
|
))
|
|
->will($this->throwException(
|
|
new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
|
|
));
|
|
|
|
$sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?alias=sentinel2');
|
|
$sentinel2->expects($this->once())
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand(
|
|
'SENTINEL', array('sentinels', 'svc')
|
|
))
|
|
->will($this->returnValue(
|
|
array(
|
|
array(
|
|
'name', '127.0.0.1:5383',
|
|
'ip', '127.0.0.1',
|
|
'port', '5383',
|
|
'runid', 'f53b52d281be5cdd4873700c94846af8dbe47209',
|
|
'flags', 'sentinel',
|
|
),
|
|
)
|
|
));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1, $sentinel2));
|
|
|
|
$replication->updateSentinels();
|
|
|
|
// TODO: sorry for the smell...
|
|
$reflection = new \ReflectionProperty($replication, 'sentinels');
|
|
$reflection->setAccessible(true);
|
|
|
|
$expected = array(
|
|
array('host' => '127.0.0.1', 'port' => '5382'),
|
|
array('host' => '127.0.0.1', 'port' => '5383'),
|
|
);
|
|
|
|
$this->assertSame($sentinel2, $replication->getSentinelConnection());
|
|
$this->assertSame($expected, array_intersect_key($expected, $reflection->getValue($replication)));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException Predis\ClientException
|
|
* @expectedExceptionMessage No sentinel server available for autodiscovery.
|
|
*/
|
|
public function testMethodUpdateSentinelsThrowsExceptionOnNoAvailableSentinel()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
$sentinel1->expects($this->once())
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand(
|
|
'SENTINEL', array('sentinels', 'svc')
|
|
))
|
|
->will($this->throwException(
|
|
new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
|
|
));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->updateSentinels();
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodQuerySentinelFetchesMasterNodeSlaveNodesAndSentinelNodes()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
$sentinel1->expects($this->exactly(3))
|
|
->method('executeCommand')
|
|
->withConsecutive(
|
|
$this->isRedisCommand('SENTINEL', array('sentinels', 'svc')),
|
|
$this->isRedisCommand('SENTINEL', array('get-master-addr-by-name', 'svc')),
|
|
$this->isRedisCommand('SENTINEL', array('slaves', 'svc'))
|
|
)
|
|
->will($this->onConsecutiveCalls(
|
|
// SENTINEL sentinels svc
|
|
array(
|
|
array(
|
|
'name', '127.0.0.1:5382',
|
|
'ip', '127.0.0.1',
|
|
'port', '5382',
|
|
'runid', 'a113aa7a0d4870a85bb22b4b605fd26eb93ed40e',
|
|
'flags', 'sentinel',
|
|
),
|
|
),
|
|
|
|
// SENTINEL get-master-addr-by-name svc
|
|
array('127.0.0.1', '6381'),
|
|
|
|
// SENTINEL slaves svc
|
|
array(
|
|
array(
|
|
'name', '127.0.0.1:6382',
|
|
'ip', '127.0.0.1',
|
|
'port', '6382',
|
|
'runid', '112cdebd22924a7d962be496f3a1c4c7c9bad93f',
|
|
'flags', 'slave',
|
|
'master-host', '127.0.0.1',
|
|
'master-port', '6381',
|
|
),
|
|
array(
|
|
'name', '127.0.0.1:6383',
|
|
'ip', '127.0.0.1',
|
|
'port', '6383',
|
|
'runid', '1c0bf1291797fbc5608c07a17da394147dc62817',
|
|
'flags', 'slave',
|
|
'master-host', '127.0.0.1',
|
|
'master-port', '6381',
|
|
),
|
|
)
|
|
));
|
|
|
|
$sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?alias=sentinel2');
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
|
|
$slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?alias=slave2');
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
$replication->querySentinel();
|
|
|
|
// TODO: sorry for the smell...
|
|
$reflection = new \ReflectionProperty($replication, 'sentinels');
|
|
$reflection->setAccessible(true);
|
|
|
|
$sentinels = array(
|
|
array('host' => '127.0.0.1', 'port' => '5381'),
|
|
array('host' => '127.0.0.1', 'port' => '5382'),
|
|
);
|
|
|
|
$this->assertSame($sentinel1, $replication->getSentinelConnection());
|
|
$this->assertSame($sentinels, array_intersect_key($sentinels, $reflection->getValue($replication)));
|
|
|
|
$master = $replication->getMaster();
|
|
$slaves = $replication->getSlaves();
|
|
|
|
$this->assertSame('127.0.0.1:6381', (string) $master);
|
|
|
|
$this->assertCount(2, $slaves);
|
|
$this->assertSame('127.0.0.1:6382', (string) $slaves[0]);
|
|
$this->assertSame('127.0.0.1:6383', (string) $slaves[1]);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodGetMasterAsksSentinelForMasterOnMasterNotSet()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
$sentinel1->expects($this->at(0))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand(
|
|
'SENTINEL', array('get-master-addr-by-name', 'svc')
|
|
))
|
|
->will($this->returnValue(
|
|
array('127.0.0.1', '6381')
|
|
));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$this->assertSame('127.0.0.1:6381', (string) $replication->getMaster());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException Predis\ClientException
|
|
* @expectedExceptionMessage No sentinel server available for autodiscovery.
|
|
*/
|
|
public function testMethodGetMasterThrowsExceptionOnNoAvailableSentinels()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
$sentinel1->expects($this->any())
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand(
|
|
'SENTINEL', array('get-master-addr-by-name', 'svc')
|
|
))
|
|
->will($this->throwException(
|
|
new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
|
|
));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->getMaster();
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodGetSlavesOnEmptySlavePoolAsksSentinelForSlaves()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
$sentinel1->expects($this->at(0))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand(
|
|
'SENTINEL', array('slaves', 'svc')
|
|
))
|
|
->will($this->returnValue(
|
|
array(
|
|
array(
|
|
'name', '127.0.0.1:6382',
|
|
'ip', '127.0.0.1',
|
|
'port', '6382',
|
|
'runid', '112cdebd22924a7d962be496f3a1c4c7c9bad93f',
|
|
'flags', 'slave',
|
|
'master-host', '127.0.0.1',
|
|
'master-port', '6381',
|
|
),
|
|
array(
|
|
'name', '127.0.0.1:6383',
|
|
'ip', '127.0.0.1',
|
|
'port', '6383',
|
|
'runid', '1c0bf1291797fbc5608c07a17da394147dc62817',
|
|
'flags', 'slave',
|
|
'master-host', '127.0.0.1',
|
|
'master-port', '6381',
|
|
),
|
|
)
|
|
));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$slaves = $replication->getSlaves();
|
|
|
|
$this->assertSame('127.0.0.1:6382', (string) $slaves[0]);
|
|
$this->assertSame('127.0.0.1:6383', (string) $slaves[1]);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException Predis\ClientException
|
|
* @expectedExceptionMessage No sentinel server available for autodiscovery.
|
|
*/
|
|
public function testMethodGetSlavesThrowsExceptionOnNoAvailableSentinels()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
$sentinel1->expects($this->any())
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand(
|
|
'SENTINEL', array('slaves', 'svc')
|
|
))
|
|
->will($this->throwException(
|
|
new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
|
|
));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->getSlaves();
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException Predis\ClientException
|
|
* @expectedExceptionMessage No sentinel server available for autodiscovery.
|
|
*/
|
|
public function testMethodConnectThrowsExceptionOnConnectWithEmptySentinelsPool()
|
|
{
|
|
$replication = $this->getReplicationConnection('svc', array());
|
|
$replication->connect();
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodConnectForcesConnectionToSlave()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$master->expects($this->never())
|
|
->method('connect');
|
|
|
|
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
|
|
$slave1->expects($this->once())
|
|
->method('connect');
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->add($master);
|
|
$replication->add($slave1);
|
|
|
|
$replication->connect();
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodConnectOnEmptySlavePoolAsksSentinelForSlavesAndForcesConnectionToSlave()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
$sentinel1->expects($this->any())
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand(
|
|
'SENTINEL', array('slaves', 'svc')
|
|
))
|
|
->will($this->returnValue(
|
|
array(
|
|
array(
|
|
'name', '127.0.0.1:6382',
|
|
'ip', '127.0.0.1',
|
|
'port', '6382',
|
|
'runid', '112cdebd22924a7d962be496f3a1c4c7c9bad93f',
|
|
'flags', 'slave',
|
|
'master-host', '127.0.0.1',
|
|
'master-port', '6381',
|
|
),
|
|
)
|
|
));
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$master->expects($this->never())
|
|
->method('connect');
|
|
|
|
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
|
|
$slave1->expects($this->once())
|
|
->method('connect');
|
|
|
|
$factory = $this->getMock('Predis\Connection\FactoryInterface');
|
|
$factory->expects($this->once())
|
|
->method('create')
|
|
->with(array(
|
|
'host' => '127.0.0.1',
|
|
'port' => '6382',
|
|
'alias' => 'slave-127.0.0.1:6382',
|
|
))
|
|
->will($this->returnValue($slave1));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1), $factory);
|
|
|
|
$replication->add($master);
|
|
|
|
$replication->connect();
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodConnectOnEmptySlavePoolAsksSentinelForSlavesAndForcesConnectionToMasterIfStillEmpty()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
$sentinel1->expects($this->at(0))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand(
|
|
'SENTINEL', array('slaves', 'svc')
|
|
))
|
|
->will($this->returnValue(
|
|
array()
|
|
));
|
|
$sentinel1->expects($this->at(1))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand(
|
|
'SENTINEL', array('get-master-addr-by-name', 'svc')
|
|
))
|
|
->will($this->returnValue(
|
|
array('127.0.0.1', '6381')
|
|
));
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$master->expects($this->once())
|
|
->method('connect');
|
|
|
|
$factory = $this->getMock('Predis\Connection\FactoryInterface');
|
|
$factory->expects($this->once())
|
|
->method('create')
|
|
->with(array(
|
|
'host' => '127.0.0.1',
|
|
'port' => '6381',
|
|
'alias' => 'master',
|
|
))
|
|
->will($this->returnValue($master));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1), $factory);
|
|
|
|
$replication->connect();
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodDisconnectForcesDisconnectionOnAllConnectionsInPool()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
$sentinel1->expects($this->never())->method('disconnect');
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$master->expects($this->once())->method('disconnect');
|
|
|
|
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
|
|
$slave1->expects($this->once())->method('disconnect');
|
|
|
|
$slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?alias=slave2');
|
|
$slave2->expects($this->once())->method('disconnect');
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->add($master);
|
|
$replication->add($slave1);
|
|
$replication->add($slave2);
|
|
|
|
$replication->disconnect();
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodIsConnectedReturnConnectionStatusOfCurrentConnection()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
|
|
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
|
|
$slave1->expects($this->exactly(2))
|
|
->method('isConnected')
|
|
->will($this->onConsecutiveCalls(true, false));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->add($slave1);
|
|
|
|
$this->assertFalse($replication->isConnected());
|
|
$replication->connect();
|
|
$this->assertTrue($replication->isConnected());
|
|
$replication->getConnectionById('slave1')->disconnect();
|
|
$this->assertFalse($replication->isConnected());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodGetConnectionByIdReturnsConnectionWhenFound()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
$replication->add($master);
|
|
$replication->add($slave1);
|
|
|
|
$this->assertSame($master, $replication->getConnectionById('master'));
|
|
$this->assertSame($slave1, $replication->getConnectionById('slave1'));
|
|
$this->assertNull($replication->getConnectionById('unknown'));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodSwitchToSelectsCurrentConnectionByConnectionAlias()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$master->expects($this->once())->method('connect');
|
|
|
|
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
|
|
$slave1->expects($this->never())->method('connect');
|
|
|
|
$slave2 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave2');
|
|
$slave2->expects($this->once())->method('connect');
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->add($master);
|
|
$replication->add($slave1);
|
|
$replication->add($slave2);
|
|
|
|
$replication->switchTo('master');
|
|
$this->assertSame($master, $replication->getCurrent());
|
|
|
|
$replication->switchTo('slave2');
|
|
$this->assertSame($slave2, $replication->getCurrent());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException InvalidArgumentException
|
|
* @expectedExceptionMessage Invalid connection or connection not found.
|
|
*/
|
|
public function testMethodSwitchToThrowsExceptionOnConnectionNotFound()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->add($master);
|
|
$replication->add($slave1);
|
|
|
|
$replication->switchTo('unknown');
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodSwitchToMasterSelectsCurrentConnectionToMaster()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$master->expects($this->once())->method('connect');
|
|
|
|
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
|
|
$slave1->expects($this->never())->method('connect');
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->add($master);
|
|
$replication->add($slave1);
|
|
|
|
$replication->switchToMaster();
|
|
|
|
$this->assertSame($master, $replication->getCurrent());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodSwitchToSlaveSelectsCurrentConnectionToRandomSlave()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$master->expects($this->never())->method('connect');
|
|
|
|
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
|
|
$slave1->expects($this->once())->method('connect');
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->add($master);
|
|
$replication->add($slave1);
|
|
|
|
$replication->switchToSlave();
|
|
|
|
$this->assertSame($slave1, $replication->getCurrent());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testGetConnectionReturnsMasterForWriteCommands()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$master->expects($this->exactly(2))
|
|
->method('isConnected')
|
|
->will($this->onConsecutiveCalls(false, true));
|
|
$master->expects($this->at(2))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('ROLE'))
|
|
->will($this->returnValue(array(
|
|
'master', 3129659, array(array('127.0.0.1', 6382, 3129242)),
|
|
)));
|
|
|
|
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->add($master);
|
|
$replication->add($slave1);
|
|
|
|
$this->assertSame($master, $replication->getConnection(
|
|
Command\RawCommand::create('set', 'key', 'value')
|
|
));
|
|
|
|
$this->assertSame($master, $replication->getConnection(
|
|
Command\RawCommand::create('del', 'key')
|
|
));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testGetConnectionReturnsSlaveForReadOnlyCommands()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
|
|
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
|
|
$slave1->expects($this->exactly(2))
|
|
->method('isConnected')
|
|
->will($this->onConsecutiveCalls(false, true));
|
|
|
|
$slave1->expects($this->at(2))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('ROLE'))
|
|
->will($this->returnValue(array(
|
|
'slave', '127.0.0.1', 9000, 'connected', 3167038,
|
|
)));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->add($master);
|
|
$replication->add($slave1);
|
|
|
|
$this->assertSame($slave1, $replication->getConnection(
|
|
Command\RawCommand::create('get', 'key')
|
|
));
|
|
|
|
$this->assertSame($slave1, $replication->getConnection(
|
|
Command\RawCommand::create('exists', 'key')
|
|
));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testGetConnectionSwitchesToMasterAfterWriteCommand()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$master->expects($this->exactly(2))
|
|
->method('isConnected')
|
|
->will($this->onConsecutiveCalls(false, true));
|
|
$master->expects($this->at(2))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('ROLE'))
|
|
->will($this->returnValue(array(
|
|
'master', 3129659, array(array('127.0.0.1', 6382, 3129242)),
|
|
)));
|
|
|
|
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
|
|
$slave1->expects($this->exactly(1))
|
|
->method('isConnected')
|
|
->will($this->onConsecutiveCalls(false));
|
|
$slave1->expects($this->at(2))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('ROLE'))
|
|
->will($this->returnValue(array(
|
|
'slave', '127.0.0.1', 9000, 'connected', 3167038,
|
|
)));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->add($master);
|
|
$replication->add($slave1);
|
|
|
|
$this->assertSame($slave1, $replication->getConnection(
|
|
Command\RawCommand::create('exists', 'key')
|
|
));
|
|
|
|
$this->assertSame($master, $replication->getConnection(
|
|
Command\RawCommand::create('set', 'key', 'value')
|
|
));
|
|
|
|
$this->assertSame($master, $replication->getConnection(
|
|
Command\RawCommand::create('get', 'key')
|
|
));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException Predis\Replication\RoleException
|
|
* @expectedExceptionMessage Expected master but got slave [127.0.0.1:6381]
|
|
*/
|
|
public function testGetConnectionThrowsExceptionOnNodeRoleMismatch()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$master->expects($this->once())
|
|
->method('isConnected')
|
|
->will($this->returnValue(false));
|
|
$master->expects($this->at(2))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('ROLE'))
|
|
->will($this->returnValue(array(
|
|
'slave', '127.0.0.1', 9000, 'connected', 3167038,
|
|
)));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->add($master);
|
|
|
|
$replication->getConnection(Command\RawCommand::create('del', 'key'));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testGetConnectionReturnsMasterForReadOnlyOperationsOnUnavailableSlaves()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
$sentinel1->expects($this->once())
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand(
|
|
'SENTINEL', array('slaves', 'svc')
|
|
))
|
|
->will($this->returnValue(
|
|
array(
|
|
array(
|
|
'name', '127.0.0.1:6382',
|
|
'ip', '127.0.0.1',
|
|
'port', '6382',
|
|
'runid', '1c0bf1291797fbc5608c07a17da394147dc62817',
|
|
'flags', 'slave,s_down,disconnected',
|
|
'master-host', '127.0.0.1',
|
|
'master-port', '6381',
|
|
),
|
|
)
|
|
));
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$master->expects($this->once())
|
|
->method('isConnected')
|
|
->will($this->returnValue(false));
|
|
$master->expects($this->at(2))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('ROLE'))
|
|
->will($this->returnValue(array(
|
|
'master', '0', array(),
|
|
)));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->add($master);
|
|
|
|
$replication->getConnection(Command\RawCommand::create('get', 'key'));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodExecuteCommandSendsCommandToNodeAndReturnsResponse()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
|
|
$cmdGet = Command\RawCommand::create('get', 'key');
|
|
$cmdGetResponse = 'value';
|
|
|
|
$cmdSet = Command\RawCommand::create('set', 'key', 'value');
|
|
$cmdSetResponse = Response\Status::get('OK');
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$master->expects($this->any())
|
|
->method('isConnected')
|
|
->will($this->returnValue(true));
|
|
$master->expects($this->at(2))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('SET', array('key', $cmdGetResponse)))
|
|
->will($this->returnValue($cmdSetResponse));
|
|
|
|
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
|
|
$slave1->expects($this->any())
|
|
->method('isConnected')
|
|
->will($this->returnValue(true));
|
|
$slave1->expects($this->at(2))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('GET', array('key')))
|
|
->will($this->returnValue($cmdGetResponse));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->add($master);
|
|
$replication->add($slave1);
|
|
|
|
$this->assertSame($cmdGetResponse, $replication->executeCommand($cmdGet));
|
|
$this->assertSame($cmdSetResponse, $replication->executeCommand($cmdSet));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodExecuteCommandRetriesReadOnlyCommandOnNextSlaveOnFailure()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
$sentinel1->expects($this->any())
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand(
|
|
'SENTINEL', array('slaves', 'svc')
|
|
))
|
|
->will($this->returnValue(
|
|
array(
|
|
array(
|
|
'name', '127.0.0.1:6383',
|
|
'ip', '127.0.0.1',
|
|
'port', '6383',
|
|
'runid', '1c0bf1291797fbc5608c07a17da394147dc62817',
|
|
'flags', 'slave',
|
|
'master-host', '127.0.0.1',
|
|
'master-port', '6381',
|
|
),
|
|
)
|
|
));
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$master->expects($this->any())
|
|
->method('isConnected')
|
|
->will($this->returnValue(true));
|
|
|
|
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
|
|
$slave1->expects($this->any())
|
|
->method('isConnected')
|
|
->will($this->returnValue(true));
|
|
$slave1->expects($this->at(2))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('GET', array('key')))
|
|
->will($this->throwException(
|
|
new Connection\ConnectionException($slave1, 'Unknown connection error [127.0.0.1:6382]')
|
|
));
|
|
|
|
$slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?alias=slave2');
|
|
$slave2->expects($this->any())
|
|
->method('isConnected')
|
|
->will($this->returnValue(true));
|
|
$slave2->expects($this->at(2))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('GET', array('key')))
|
|
->will($this->returnValue('value'));
|
|
|
|
$factory = $this->getMock('Predis\Connection\FactoryInterface');
|
|
$factory->expects($this->once())
|
|
->method('create')
|
|
->with(array(
|
|
'host' => '127.0.0.1',
|
|
'port' => '6383',
|
|
'alias' => 'slave-127.0.0.1:6383',
|
|
))
|
|
->will($this->returnValue($slave2));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1), $factory);
|
|
|
|
$replication->add($master);
|
|
$replication->add($slave1);
|
|
|
|
$this->assertSame('value', $replication->executeCommand(
|
|
Command\RawCommand::create('get', 'key')
|
|
));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodExecuteCommandRetriesWriteCommandOnNewMasterOnFailure()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
$sentinel1->expects($this->any())
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand(
|
|
'SENTINEL', array('get-master-addr-by-name', 'svc')
|
|
))
|
|
->will($this->returnValue(
|
|
array('127.0.0.1', '6391')
|
|
));
|
|
|
|
$masterOld = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$masterOld->expects($this->any())
|
|
->method('isConnected')
|
|
->will($this->returnValue(true));
|
|
$masterOld->expects($this->at(2))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('DEL', array('key')))
|
|
->will($this->throwException(
|
|
new Connection\ConnectionException($masterOld, 'Unknown connection error [127.0.0.1:6381]')
|
|
));
|
|
|
|
$masterNew = $this->getMockConnection('tcp://127.0.0.1:6391?alias=master');
|
|
$masterNew->expects($this->any())
|
|
->method('isConnected')
|
|
->will($this->returnValue(true));
|
|
$masterNew->expects($this->at(2))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('DEL', array('key')))
|
|
->will($this->returnValue(1));
|
|
|
|
$factory = $this->getMock('Predis\Connection\FactoryInterface');
|
|
$factory->expects($this->once())
|
|
->method('create')
|
|
->with(array(
|
|
'host' => '127.0.0.1',
|
|
'port' => '6391',
|
|
'alias' => 'master',
|
|
))
|
|
->will($this->returnValue($masterNew));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1), $factory);
|
|
|
|
$replication->add($masterOld);
|
|
|
|
$this->assertSame(1, $replication->executeCommand(
|
|
Command\RawCommand::create('del', 'key')
|
|
));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException Predis\Response\ServerException
|
|
* @expectedExceptionMessage ERR No such master with that name
|
|
*/
|
|
public function testMethodExecuteCommandThrowsExceptionOnUnknownServiceName()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
$sentinel1->expects($this->any())
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand(
|
|
'SENTINEL', array('get-master-addr-by-name', 'svc')
|
|
))
|
|
->will($this->returnValue(null));
|
|
|
|
$masterOld = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$masterOld->expects($this->any())
|
|
->method('isConnected')
|
|
->will($this->returnValue(true));
|
|
$masterOld->expects($this->at(2))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('DEL', array('key')))
|
|
->will($this->throwException(
|
|
new Connection\ConnectionException($masterOld, 'Unknown connection error [127.0.0.1:6381]')
|
|
));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->add($masterOld);
|
|
|
|
$replication->executeCommand(
|
|
Command\RawCommand::create('del', 'key')
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException Predis\ClientException
|
|
* @expectedExceptionMessage No sentinel server available for autodiscovery.
|
|
*/
|
|
public function testMethodExecuteCommandThrowsExceptionOnConnectionFailureAndNoAvailableSentinels()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
$sentinel1->expects($this->any())
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand(
|
|
'SENTINEL', array('get-master-addr-by-name', 'svc')
|
|
))
|
|
->will($this->throwException(
|
|
new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
|
|
));
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$master->expects($this->any())
|
|
->method('isConnected')
|
|
->will($this->returnValue(true));
|
|
$master->expects($this->at(2))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('DEL', array('key')))
|
|
->will($this->throwException(
|
|
new Connection\ConnectionException($master, 'Unknown connection error [127.0.0.1:6381]')
|
|
));
|
|
|
|
$replication = $this->getReplicationConnection('svc', array($sentinel1));
|
|
|
|
$replication->add($master);
|
|
|
|
$replication->executeCommand(
|
|
Command\RawCommand::create('del', 'key')
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodGetReplicationStrategyReturnsInstance()
|
|
{
|
|
$strategy = new Replication\ReplicationStrategy();
|
|
$factory = new Connection\Factory();
|
|
|
|
$replication = new SentinelReplication(
|
|
'svc', array('tcp://127.0.0.1:5381?alias=sentinel1'), $factory, $strategy
|
|
);
|
|
|
|
$this->assertSame($strategy, $replication->getReplicationStrategy());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMethodSerializeCanSerializeWholeObject()
|
|
{
|
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
|
|
|
|
$master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
|
|
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
|
|
$slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?alias=slave2');
|
|
|
|
$strategy = new Replication\ReplicationStrategy();
|
|
$factory = new Connection\Factory();
|
|
|
|
$replication = new SentinelReplication('svc', array($sentinel1), $factory, $strategy);
|
|
|
|
$replication->add($master);
|
|
$replication->add($slave1);
|
|
$replication->add($slave2);
|
|
|
|
$unserialized = unserialize(serialize($replication));
|
|
|
|
$this->assertEquals($master, $unserialized->getConnectionById('master'));
|
|
$this->assertEquals($slave1, $unserialized->getConnectionById('slave1'));
|
|
$this->assertEquals($master, $unserialized->getConnectionById('slave2'));
|
|
$this->assertEquals($strategy, $unserialized->getReplicationStrategy());
|
|
}
|
|
|
|
// ******************************************************************** //
|
|
// ---- HELPER METHODS ------------------------------------------------ //
|
|
// ******************************************************************** //
|
|
|
|
/**
|
|
* Creates a new instance of replication connection.
|
|
*
|
|
* @param string $service Name of the service
|
|
* @param array $sentinels Array of sentinels
|
|
* @param ConnectionFactoryInterface|null $factory Optional connection factory instance.
|
|
*
|
|
* @return SentinelReplication
|
|
*/
|
|
protected function getReplicationConnection($service, $sentinels, Connection\FactoryInterface $factory = null)
|
|
{
|
|
$factory = $factory ?: new Connection\Factory();
|
|
|
|
$replication = new SentinelReplication($service, $sentinels, $factory);
|
|
$replication->setRetryWait(0);
|
|
|
|
return $replication;
|
|
}
|
|
|
|
/**
|
|
* Returns a base mocked connection from Predis\Connection\NodeConnectionInterface.
|
|
*
|
|
* @param mixed $parameters Optional parameters.
|
|
*
|
|
* @return mixed
|
|
*/
|
|
protected function getMockSentinelConnection($parameters = null)
|
|
{
|
|
$connection = $this->getMockConnection($parameters);
|
|
|
|
return $connection;
|
|
}
|
|
}
|