mirror of
https://github.com/predis/predis.git
synced 2026-08-18 15:01:47 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6e8e23279e | |||
| 0392208520 | |||
| d9de9b5df3 |
@@ -48,6 +48,14 @@ v2.0.0 (202x-xx-xx)
|
||||
get a single connection from the pool by using its ID. It is also possible to
|
||||
retrive a connection by role using the method getConnectionByRole().
|
||||
|
||||
- It is possible to set `role`-specific default parameters via the `parameters`
|
||||
client option by passing named arrays to the following keys: `role.sentinel`,
|
||||
`role.master` and `role.slave`. These parameters take precedence over global
|
||||
default parameters but, as usual, they do not override parameters explicitly
|
||||
set by users for each single node connection. For sentinels, "username" and
|
||||
"database" are always stripped because they are not supported while "password"
|
||||
is never inherited from global default parameters and must be set explicitly.
|
||||
|
||||
- The concept of connection ID (ip:port pair) and connection alias (the `alias`
|
||||
parameter) in `Predis\Connection\Cluster\PredisCluster` has been separated.
|
||||
This change does not affect distribution and it is safe for existing clusters.
|
||||
|
||||
@@ -169,6 +169,40 @@ Users can also provide custom options with values or callable objects (for lazy
|
||||
are stored in the options container for later use through the library.
|
||||
|
||||
|
||||
### Global and role-specific default connection parameters ###
|
||||
|
||||
While the `parameters` client option is useful to apply a set of default parameters and their values
|
||||
to connections created by the underlying connection factory, sometimes it is useful to set different
|
||||
values depending on the actual role of the target node (just to make an example, for sentinel nodes
|
||||
it is common to use a lower connect() timeout compared to the default value for normal Redis nodes).
|
||||
To make this possible `parameters` allows passing role-specific default values as named arrays using
|
||||
three special keys: `role.sentinel`, `role.master` and `role.slave`. These role-specific parameters
|
||||
take precedence over global default parameters passed at the root level of `parameters` but they do
|
||||
not override parameters explicitly set by the user for each single node just like global defaults.
|
||||
|
||||
```php
|
||||
$options = [
|
||||
'parameters' => [
|
||||
// Root level is for global default parameters.
|
||||
'database' => 10,
|
||||
'password' => $redisSecretPassword,
|
||||
|
||||
// ...
|
||||
|
||||
'role.master' => [
|
||||
// Sub-key for default parameters targeting master Redis nodes.
|
||||
],
|
||||
'role.slave' => [
|
||||
// Sub-key for default parameters targeting replica Redis nodes.
|
||||
],
|
||||
'role.sentinel' => [
|
||||
// Sub-key for default parameters targeting Redis Sentinel nodes.
|
||||
],
|
||||
],
|
||||
];
|
||||
```
|
||||
|
||||
|
||||
### Aggregate connections ###
|
||||
|
||||
Aggregate connections are the foundation upon which Predis implements clustering and replication and
|
||||
@@ -234,22 +268,38 @@ the `service` option set to the name of the service:
|
||||
|
||||
```php
|
||||
$sentinels = ['tcp://10.0.0.1', 'tcp://10.0.0.2', 'tcp://10.0.0.3'];
|
||||
$options = ['replication' => 'sentinel', 'service' => 'mymaster'];
|
||||
$options = ['replication' => 'sentinel', 'service' => 'myservice'];
|
||||
|
||||
$client = new Predis\Client($sentinels, $options);
|
||||
```
|
||||
|
||||
If the master and slave nodes are configured to require an authentication from clients, a password
|
||||
must be provided via the global `parameters` client option. This option can also be used to specify
|
||||
a different database index. The client options array would then look like this:
|
||||
When master and replica nodes are configured to require authentication from clients, users must pass
|
||||
`password` (password-based authentication) or `username` and `password` (ACL-based authentication on
|
||||
Redis >= 6.0) via the global `parameters` client option.
|
||||
|
||||
```php
|
||||
$options = [
|
||||
'replication' => 'sentinel',
|
||||
'service' => 'mymaster',
|
||||
'service' => 'myservice',
|
||||
'parameters' => [
|
||||
'password' => $secretpassword,
|
||||
'database' => 10,
|
||||
'password' => $secretRedisPassword,
|
||||
],
|
||||
];
|
||||
```
|
||||
|
||||
For sentinels protected by a password (supported since Redis >= 5.0) its value is not inherited from
|
||||
the global `parameters` client option so a `password` must be set using the `role.sentinel` sub-key:
|
||||
|
||||
```php
|
||||
$options = [
|
||||
'replication' => 'sentinel',
|
||||
'service' => 'myservice',
|
||||
'parameters' => [
|
||||
'password' => $secretRedisPassword,
|
||||
|
||||
'role.sentinel' => [
|
||||
'password' => $secretSentinelPassword
|
||||
]
|
||||
],
|
||||
];
|
||||
```
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
namespace Predis\Connection;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Predis\Command\RawCommand;
|
||||
|
||||
/**
|
||||
@@ -119,6 +120,28 @@ class Factory implements FactoryInterface
|
||||
*/
|
||||
public function setDefaultParameters(array $parameters)
|
||||
{
|
||||
if (isset($parameters['role.master']) && !is_array($parameters['role.master'])) {
|
||||
throw new InvalidArgumentException('Default parameters for `role.master` must be passed as a named array');
|
||||
}
|
||||
|
||||
if (isset($parameters['role.slave']) && !is_array($parameters['role.slave'])) {
|
||||
throw new InvalidArgumentException('Default parameters for `role.slave` must be passed as a named array');
|
||||
}
|
||||
|
||||
if (isset($parameters['role.sentinel'])) {
|
||||
if (!is_array($parameters['role.sentinel'])) {
|
||||
throw new InvalidArgumentException('Default parameters for `role.sentinel` must be passed as a named array');
|
||||
}
|
||||
|
||||
// NOTE: sentinels do not support "SELECT" and ACL "AUTH" commands
|
||||
// so we must strip "database" and "username" from "role.sentinel"
|
||||
// to prevent spurious commands from being sent to sentinel nodes.
|
||||
unset(
|
||||
$parameters['role.sentinel']['username'],
|
||||
$parameters['role.sentinel']['database']
|
||||
);
|
||||
}
|
||||
|
||||
$this->defaults = $parameters;
|
||||
}
|
||||
|
||||
@@ -132,6 +155,37 @@ class Factory implements FactoryInterface
|
||||
return $this->defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies default connection parameters to the user supplied parameters.
|
||||
*
|
||||
* @param array $parameters Input connection parameters
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function applyDefaultParameters(array $parameters)
|
||||
{
|
||||
static $stripInternal = ['role.sentinel' => null, 'role.master' => null, 'role.slave' => null];
|
||||
|
||||
$stripAdditional = [];
|
||||
|
||||
if (isset($parameters['role'])) {
|
||||
switch ($role = $parameters['role']) {
|
||||
case 'sentinel':
|
||||
// NOTE: we strip these from global defaults when dealing with sentinel nodes.
|
||||
$stripAdditional = ['username' => null, 'password' => null, 'database' => null];
|
||||
case 'master':
|
||||
case 'slave':
|
||||
if (isset($this->defaults["role.$role"])) {
|
||||
$parameters += $this->defaults["role.$role"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$parameters += array_diff_key($this->defaults, $stripInternal, $stripAdditional);
|
||||
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a connection parameters instance from the supplied argument.
|
||||
*
|
||||
@@ -144,11 +198,19 @@ class Factory implements FactoryInterface
|
||||
if (is_string($parameters)) {
|
||||
$parameters = Parameters::parse($parameters);
|
||||
} else {
|
||||
$parameters = $parameters ?: array();
|
||||
$parameters = $parameters ?? [];
|
||||
}
|
||||
|
||||
if (isset($parameters['role']) && $parameters['role'] === 'sentinel') {
|
||||
// NOTE: sentinels do not support "SELECT" and ACL "AUTH" commands so we must strip
|
||||
// "database" and "username" from input parameters to prevent spurious commands from
|
||||
// being sent to sentinel nodes but they can still accept "password" when explicitly
|
||||
// set (password-based authentication for sentinels is supported on Redis >= 5.0).
|
||||
unset($parameters['username'], $parameters['database']);
|
||||
}
|
||||
|
||||
if ($this->defaults) {
|
||||
$parameters += $this->defaults;
|
||||
$parameters = $this->applyDefaultParameters($parameters);
|
||||
}
|
||||
|
||||
return new Parameters($parameters);
|
||||
|
||||
@@ -241,6 +241,8 @@ class SentinelReplication implements ReplicationInterface
|
||||
/**
|
||||
* Creates a new connection to a sentinel server.
|
||||
*
|
||||
* @param mixed $parameters Connection parameters or connection instance
|
||||
*
|
||||
* @return NodeConnectionInterface
|
||||
*/
|
||||
protected function createSentinelConnection($parameters)
|
||||
@@ -254,12 +256,10 @@ class SentinelReplication implements ReplicationInterface
|
||||
}
|
||||
|
||||
if (is_array($parameters)) {
|
||||
// Password authentication is fine now that Redis Sentinel supports
|
||||
// password-protected sentinel instances, but we must explicitly set
|
||||
// "database" and "username" to NULL so that no augmented AUTH (ACL)
|
||||
// and SELECT command are sent by accident to the sentinels.
|
||||
$parameters['database'] = null;
|
||||
$parameters['username'] = null;
|
||||
// NOTE: we enforce the "sentinel" role so that appropriate default
|
||||
// parameters are applied when creating the new connection instance
|
||||
// and blacklisted ones are stripped off from input parameters.
|
||||
$parameters['role'] = 'sentinel';
|
||||
|
||||
if (!isset($parameters['timeout'])) {
|
||||
$parameters['timeout'] = $this->sentinelTimeout;
|
||||
|
||||
@@ -44,8 +44,108 @@ class FactoryTest extends PredisTestCase
|
||||
));
|
||||
|
||||
$this->assertSame($defaults, $factory->getDefaultParameters());
|
||||
}
|
||||
|
||||
$parameters = array('database' => 10, 'persistent' => true);
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testSettingDefaultParametersForMasterRole(): void
|
||||
{
|
||||
$factory = new Factory();
|
||||
|
||||
$factory->setDefaultParameters($expected = array(
|
||||
'role.master' => [
|
||||
'username' => 'myusername',
|
||||
'password' => 'secret',
|
||||
'database' => 10,
|
||||
]
|
||||
));
|
||||
|
||||
$this->assertSame($expected, $factory->getDefaultParameters());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testSettingDefaultParametersForMasterRoleAcceptsArrayOnly(): void
|
||||
{
|
||||
$this->expectException('InvalidArgumentException');
|
||||
$this->expectExceptionMessage('Default parameters for `role.master` must be passed as a named array');
|
||||
|
||||
$factory = new Factory();
|
||||
$factory->setDefaultParameters(array(
|
||||
'role.master' => 'invalid value',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testSettingDefaultParametersForSlaveRole(): void
|
||||
{
|
||||
$factory = new Factory();
|
||||
|
||||
$factory->setDefaultParameters($expected = array(
|
||||
'role.slave' => [
|
||||
'username' => 'myusername',
|
||||
'password' => 'secret',
|
||||
'database' => 10,
|
||||
]
|
||||
));
|
||||
|
||||
$this->assertSame($expected, $factory->getDefaultParameters());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testSettingDefaultParametersForSlaveRoleAcceptsArrayOnly(): void
|
||||
{
|
||||
$this->expectException('InvalidArgumentException');
|
||||
$this->expectExceptionMessage('Default parameters for `role.slave` must be passed as a named array');
|
||||
|
||||
$factory = new Factory();
|
||||
$factory->setDefaultParameters(array(
|
||||
'role.slave' => 'invalid value',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testSettingDefaultParametersForSentinelRoleIgnoresUsernameAndPassword(): void
|
||||
{
|
||||
$factory = new Factory();
|
||||
|
||||
$factory->setDefaultParameters(array(
|
||||
'role.sentinel' => [
|
||||
'username' => 'myusername',
|
||||
'password' => 'secret',
|
||||
'database' => 10,
|
||||
]
|
||||
));
|
||||
|
||||
$expected = array(
|
||||
'role.sentinel' => [
|
||||
'password' => 'secret',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertSame($expected, $factory->getDefaultParameters());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testSettingDefaultParametersForSentinelRoleAcceptsArrayOnly(): void
|
||||
{
|
||||
$this->expectException('InvalidArgumentException');
|
||||
$this->expectExceptionMessage('Default parameters for `role.sentinel` must be passed as a named array');
|
||||
|
||||
$factory = new Factory();
|
||||
$factory->setDefaultParameters(array(
|
||||
'role.sentinel' => 'invalid value',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,7 +295,7 @@ class FactoryTest extends PredisTestCase
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testCreateConnectionWithArrayParametersAndDefaults(): void
|
||||
public function testCreateConnectionWithDefaultParametersDoNotOverrideExplicitInputParameters(): void
|
||||
{
|
||||
$factory = new Factory();
|
||||
|
||||
@@ -223,6 +323,218 @@ class FactoryTest extends PredisTestCase
|
||||
$this->assertNull($parameters->path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testCreateConnectionForSentinelRoleIgnoresUsernameAndDatabase(): void
|
||||
{
|
||||
$factory = new Factory();
|
||||
|
||||
$connection = $factory->create($inputParams = array(
|
||||
'role' => 'sentinel',
|
||||
'username' => 'myusername',
|
||||
'password' => 'mypassword',
|
||||
'database' => 10,
|
||||
));
|
||||
|
||||
$parameters = $connection->getParameters();
|
||||
|
||||
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
|
||||
|
||||
$this->assertEquals($inputParams['role'], $parameters->role);
|
||||
$this->assertEquals($inputParams['password'], $parameters->password);
|
||||
$this->assertNull($parameters->username);
|
||||
$this->assertNull($parameters->database);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testCreateConnectionForSentinelRoleDoesNotInheritPasswordFromGlobalDefaultParameters(): void
|
||||
{
|
||||
$factory = new Factory();
|
||||
|
||||
$factory->setDefaultParameters($defaultParams = array(
|
||||
'password' => 'pwd.default',
|
||||
));
|
||||
|
||||
$connectionSentinelRole = $factory->create($inputParamsSentinelRole = array(
|
||||
'role' => 'sentinel',
|
||||
));
|
||||
|
||||
$parameters = $connectionSentinelRole->getParameters();
|
||||
$this->assertNull($parameters->password);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testCreateConnectionForSentinelRoleDoesNotInheritUsernameFromGlobalDefaultParameters(): void
|
||||
{
|
||||
$factory = new Factory();
|
||||
|
||||
$factory->setDefaultParameters($defaultParams = array(
|
||||
'username' => 'usr.default',
|
||||
));
|
||||
|
||||
$connectionSentinelRole = $factory->create($inputParamsSentinelRole = array(
|
||||
'role' => 'sentinel',
|
||||
));
|
||||
|
||||
$parameters = $connectionSentinelRole->getParameters();
|
||||
$this->assertNull($parameters->username);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testCreateConnectionForSentinelRoleDoesNotInheritDatabaseFromGlobalDefaultParameters(): void
|
||||
{
|
||||
$factory = new Factory();
|
||||
|
||||
$factory->setDefaultParameters($defaultParams = array(
|
||||
'database' => 15,
|
||||
));
|
||||
|
||||
$connectionSentinelRole = $factory->create($inputParamsSentinelRole = array(
|
||||
'role' => 'sentinel',
|
||||
));
|
||||
|
||||
$parameters = $connectionSentinelRole->getParameters();
|
||||
$this->assertNull($parameters->database);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testCreateConnectionWithDefaultRoleParametersDoNotOverrideExplicitInputParameters(): void
|
||||
{
|
||||
$factory = new Factory();
|
||||
|
||||
$factory->setDefaultParameters($defaultParams = array(
|
||||
'timeout' => 20,
|
||||
'password' => 'pwd.default.norole',
|
||||
|
||||
'role.master' => [
|
||||
'password' => 'pwd.role.master',
|
||||
'timeout' => 10,
|
||||
],
|
||||
'role.slave' => [
|
||||
'password' => 'pwd.role.slave',
|
||||
'timeout' => 5,
|
||||
],
|
||||
'role.sentinel' => [
|
||||
'password' => 'pwd.role.sentinel',
|
||||
'timeout' => 1,
|
||||
],
|
||||
));
|
||||
|
||||
// NO ROLE
|
||||
$connectionNoRole = $factory->create($inputParamsNoRole = array(
|
||||
'password' => 'pwd.local.norole',
|
||||
'timeout' => 30,
|
||||
));
|
||||
|
||||
$parameters = $connectionNoRole->getParameters();
|
||||
$this->assertEquals('pwd.local.norole', $parameters->password);
|
||||
$this->assertEquals(30, $parameters->timeout);
|
||||
|
||||
// ROLE MASTER
|
||||
$connectionMasterRole = $factory->create($inputParamsMasterRole = array(
|
||||
'role' => 'master',
|
||||
'password' => 'pwd.local.master',
|
||||
'timeout' => 30,
|
||||
));
|
||||
|
||||
$parameters = $connectionMasterRole->getParameters();
|
||||
$this->assertEquals('pwd.local.master', $parameters->password);
|
||||
$this->assertEquals(30, $parameters->timeout);
|
||||
|
||||
// ROLE SLAVE
|
||||
$connectionSlaveRole = $factory->create($inputParamsSlaveRole = array(
|
||||
'role' => 'slave',
|
||||
'password' => 'pwd.local.slave',
|
||||
'timeout' => 30,
|
||||
));
|
||||
|
||||
$parameters = $connectionSlaveRole->getParameters();
|
||||
$this->assertEquals('pwd.local.slave', $parameters->password);
|
||||
$this->assertEquals(30, $parameters->timeout);
|
||||
|
||||
// ROLE SENTINEL
|
||||
$connectionSentinelRole = $factory->create($inputParamsSentinelRole = array(
|
||||
'role' => 'slave',
|
||||
'password' => 'pwd.local.sentinel',
|
||||
'timeout' => 30,
|
||||
));
|
||||
|
||||
$parameters = $connectionSentinelRole->getParameters();
|
||||
$this->assertEquals('pwd.local.sentinel', $parameters->password);
|
||||
$this->assertEquals(30, $parameters->timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testCreateConnectionWithDefaultRoleParametersOverridesDefaultGlobalParameters(): void
|
||||
{
|
||||
$factory = new Factory();
|
||||
|
||||
$factory->setDefaultParameters($defaultParams = array(
|
||||
'timeout' => 20,
|
||||
'password' => 'pwd.default.norole',
|
||||
|
||||
'role.master' => [
|
||||
'password' => 'pwd.role.master',
|
||||
'timeout' => 10,
|
||||
],
|
||||
'role.slave' => [
|
||||
'password' => 'pwd.role.slave',
|
||||
'timeout' => 5,
|
||||
],
|
||||
'role.sentinel' => [
|
||||
'password' => 'pwd.role.sentinel',
|
||||
'timeout' => 1,
|
||||
],
|
||||
));
|
||||
|
||||
// NO ROLE
|
||||
$connectionNoRole = $factory->create($inputParamsNoRole = array(
|
||||
// EMPTY
|
||||
));
|
||||
|
||||
$parameters = $connectionNoRole->getParameters();
|
||||
$this->assertEquals('pwd.default.norole', $parameters->password);
|
||||
$this->assertEquals(20, $parameters->timeout);
|
||||
|
||||
// ROLE MASTER
|
||||
$connectionMasterRole = $factory->create($inputParamsMasterRole = array(
|
||||
'role' => 'master',
|
||||
));
|
||||
|
||||
$parameters = $connectionMasterRole->getParameters();
|
||||
$this->assertEquals('pwd.role.master', $parameters->password);
|
||||
$this->assertEquals(10, $parameters->timeout);
|
||||
|
||||
// ROLE SLAVE
|
||||
$connectionSlaveRole = $factory->create($inputParamsSlaveRole = array(
|
||||
'role' => 'slave',
|
||||
));
|
||||
|
||||
$parameters = $connectionSlaveRole->getParameters();
|
||||
$this->assertEquals('pwd.role.slave', $parameters->password);
|
||||
$this->assertEquals(5, $parameters->timeout);
|
||||
|
||||
// ROLE SENTINEL
|
||||
$connectionSentinelRole = $factory->create($inputParamsSentinelRole = array(
|
||||
'role' => 'sentinel',
|
||||
));
|
||||
|
||||
$parameters = $connectionSentinelRole->getParameters();
|
||||
$this->assertEquals('pwd.role.sentinel', $parameters->password);
|
||||
$this->assertEquals(1, $parameters->timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
|
||||
@@ -41,7 +41,7 @@ class SentinelReplicationTest extends PredisTestCase
|
||||
public function testParametersForSentinelConnectionShouldUsePasswordForAuthentication(): void
|
||||
{
|
||||
$replication = $this->getReplicationConnection('svc', array(
|
||||
'tcp://127.0.0.1:5381?alias=sentinel1&password=secret',
|
||||
'tcp://127.0.0.1:5381?password=secret',
|
||||
));
|
||||
|
||||
$parameters = $replication->getSentinelConnection()->getParameters()->toArray();
|
||||
@@ -122,9 +122,9 @@ class SentinelReplicationTest extends PredisTestCase
|
||||
*/
|
||||
public function testMethodGetSentinelConnectionReturnsFirstAvailableSentinel(): void
|
||||
{
|
||||
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?role=sentinel&alias=sentinel1');
|
||||
$sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?role=sentinel&alias=sentinel2');
|
||||
$sentinel3 = $this->getMockSentinelConnection('tcp://127.0.0.1:5383?role=sentinel&alias=sentinel3');
|
||||
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?role=sentinel');
|
||||
$sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?role=sentinel');
|
||||
$sentinel3 = $this->getMockSentinelConnection('tcp://127.0.0.1:5383?role=sentinel');
|
||||
|
||||
$replication = $this->getReplicationConnection('svc', array($sentinel1, $sentinel2, $sentinel3));
|
||||
|
||||
@@ -305,15 +305,16 @@ class SentinelReplicationTest extends PredisTestCase
|
||||
// TODO: sorry for the smell...
|
||||
$reflection = new \ReflectionProperty($replication, 'sentinels');
|
||||
$reflection->setAccessible(true);
|
||||
$retrievedSentinels = $reflection->getValue($replication);
|
||||
|
||||
$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'),
|
||||
$expectedSentinels = array(
|
||||
array('scheme' => 'tcp', 'host' => '127.0.0.1', 'port' => '5381', 'role' => 'sentinel'),
|
||||
array('host' => '127.0.0.1', 'port' => '5382', 'role' => 'sentinel'),
|
||||
array('host' => '127.0.0.1', 'port' => '5383', 'role' => 'sentinel'),
|
||||
);
|
||||
|
||||
$this->assertSame($sentinel1, $replication->getSentinelConnection());
|
||||
$this->assertSame($expected, array_intersect_key($expected, $reflection->getValue($replication)));
|
||||
$this->assertEquals($expectedSentinels, $retrievedSentinels);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -321,7 +322,7 @@ class SentinelReplicationTest extends PredisTestCase
|
||||
*/
|
||||
public function testMethodUpdateSentinelsRemovesCurrentSentinelAndRetriesNextOneOnFailure(): void
|
||||
{
|
||||
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?role=sentinel&alias=sentinel1');
|
||||
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?role=sentinel');
|
||||
$sentinel1
|
||||
->expects($this->once())
|
||||
->method('executeCommand')
|
||||
@@ -332,7 +333,7 @@ class SentinelReplicationTest extends PredisTestCase
|
||||
new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
|
||||
);
|
||||
|
||||
$sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?role=sentinel&alias=sentinel2');
|
||||
$sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?role=sentinel');
|
||||
$sentinel2
|
||||
->expects($this->once())
|
||||
->method('executeCommand')
|
||||
@@ -357,14 +358,15 @@ class SentinelReplicationTest extends PredisTestCase
|
||||
// TODO: sorry for the smell...
|
||||
$reflection = new \ReflectionProperty($replication, 'sentinels');
|
||||
$reflection->setAccessible(true);
|
||||
$retrievedSentinels = $reflection->getValue($replication);
|
||||
|
||||
$expected = array(
|
||||
array('host' => '127.0.0.1', 'port' => '5382'),
|
||||
array('host' => '127.0.0.1', 'port' => '5383'),
|
||||
$expectedSentinels = array(
|
||||
array('scheme' => 'tcp', 'host' => '127.0.0.1', 'port' => '5382', 'role' => 'sentinel'),
|
||||
array('host' => '127.0.0.1', 'port' => '5383', 'role' => 'sentinel'),
|
||||
);
|
||||
|
||||
$this->assertSame($sentinel2, $replication->getSentinelConnection());
|
||||
$this->assertSame($expected, array_intersect_key($expected, $reflection->getValue($replication)));
|
||||
$this->assertEquals($expectedSentinels, $retrievedSentinels);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -395,7 +397,7 @@ class SentinelReplicationTest extends PredisTestCase
|
||||
*/
|
||||
public function testMethodQuerySentinelFetchesMasterNodeSlaveNodesAndSentinelNodes(): void
|
||||
{
|
||||
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?role=sentinel&alias=sentinel1');
|
||||
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?role=sentinel');
|
||||
$sentinel1
|
||||
->expects($this->exactly(3))
|
||||
->method('executeCommand')
|
||||
@@ -442,7 +444,7 @@ class SentinelReplicationTest extends PredisTestCase
|
||||
)
|
||||
);
|
||||
|
||||
$sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?role=sentinel&alias=sentinel2');
|
||||
$sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?role=sentinel');
|
||||
|
||||
$master = $this->getMockConnection('tcp://127.0.0.1:6381?role=master');
|
||||
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?role=slave');
|
||||
@@ -454,14 +456,15 @@ class SentinelReplicationTest extends PredisTestCase
|
||||
// TODO: sorry for the smell...
|
||||
$reflection = new \ReflectionProperty($replication, 'sentinels');
|
||||
$reflection->setAccessible(true);
|
||||
$retrievedSentinels = $reflection->getValue($replication);
|
||||
|
||||
$sentinels = array(
|
||||
array('host' => '127.0.0.1', 'port' => '5381'),
|
||||
array('host' => '127.0.0.1', 'port' => '5382'),
|
||||
$expectedSentinels = array(
|
||||
array('scheme' => 'tcp', 'host' => '127.0.0.1', 'port' => '5381', 'role' => 'sentinel'),
|
||||
array('host' => '127.0.0.1', 'port' => '5382', 'role' => 'sentinel'),
|
||||
);
|
||||
|
||||
$this->assertSame($sentinel1, $replication->getSentinelConnection());
|
||||
$this->assertSame($sentinels, array_intersect_key($sentinels, $reflection->getValue($replication)));
|
||||
$this->assertEquals($expectedSentinels, $retrievedSentinels);
|
||||
|
||||
$master = $replication->getMaster();
|
||||
$slaves = $replication->getSlaves();
|
||||
|
||||
Reference in New Issue
Block a user