Use SENTINEL REPLICAS for Sentinel replica discovery
This commit is contained in:
1 parent
23adb182a0
commit
6ea16b84c7
4 files changed
+90
-17
No files matched your search
@@ -4,6 +4,9 @@
|
|||||||
### Added
|
### Added
|
||||||
- Added support for numbered databases in Valkey clusters (#1696)
|
- Added support for numbered databases in Valkey clusters (#1696)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Use `SENTINEL REPLICAS` for Sentinel replica discovery, falling back to `SENTINEL SLAVES` on Redis < 5.0 (#776)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Fixed interrupted pipelines leaving unread replies on reused connections; failed pipelines now discard remaining commands and reset execution state (#1309)
|
- Fixed interrupted pipelines leaving unread replies on reused connections; failed pipelines now discard remaining commands and reset execution state (#1309)
|
||||||
- Fixed Relay Pub/Sub subscriptions rejecting message callbacks and failing when the `prefix` option is set (#1292)
|
- Fixed Relay Pub/Sub subscriptions rejecting message callbacks and failing when the `prefix` option is set (#1292)
|
||||||
|
|||||||
@@ -424,9 +424,16 @@ class SentinelReplication extends AbstractAggregateConnection implements Replica
|
|||||||
$slaves = [];
|
$slaves = [];
|
||||||
|
|
||||||
$payload = $sentinel->executeCommand(
|
$payload = $sentinel->executeCommand(
|
||||||
RawCommand::create('SENTINEL', 'slaves', $service)
|
RawCommand::create('SENTINEL', 'replicas', $service)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// NOTE: SENTINEL REPLICAS is available since Redis 5.0, older sentinels only know SENTINEL SLAVES.
|
||||||
|
if ($payload instanceof ErrorResponseInterface && stripos($payload->getMessage(), 'unknown sentinel subcommand') !== false) {
|
||||||
|
$payload = $sentinel->executeCommand(
|
||||||
|
RawCommand::create('SENTINEL', 'slaves', $service)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if ($payload instanceof ErrorResponseInterface) {
|
if ($payload instanceof ErrorResponseInterface) {
|
||||||
$this->handleSentinelErrorResponse($sentinel, $payload);
|
$this->handleSentinelErrorResponse($sentinel, $payload);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1729,7 +1729,7 @@ class ClientTest extends PredisTestCase
|
|||||||
|
|
||||||
$this->assertInstanceOf(SentinelReplication::class, $connection);
|
$this->assertInstanceOf(SentinelReplication::class, $connection);
|
||||||
|
|
||||||
// SENTINEL slaves returns a map under RESP3 - calling getSlaves()
|
// SENTINEL replicas returns a map under RESP3 - calling getSlaves()
|
||||||
// exercises the parsing path that previously read fields by
|
// exercises the parsing path that previously read fields by
|
||||||
// positional index. We do not assert on cardinality because the
|
// positional index. We do not assert on cardinality because the
|
||||||
// CI topology may not include replicas; we only require that the
|
// CI topology may not include replicas; we only require that the
|
||||||
|
|||||||
@@ -298,13 +298,13 @@ class SentinelReplicationTest extends PredisTestCase
|
|||||||
->method('executeCommand')
|
->method('executeCommand')
|
||||||
->withConsecutive(
|
->withConsecutive(
|
||||||
[$this->isRedisCommand('SENTINEL', ['get-master-addr-by-name', 'svc'])],
|
[$this->isRedisCommand('SENTINEL', ['get-master-addr-by-name', 'svc'])],
|
||||||
[$this->isRedisCommand('SENTINEL', ['slaves', 'svc'])]
|
[$this->isRedisCommand('SENTINEL', ['replicas', 'svc'])]
|
||||||
)
|
)
|
||||||
->willReturnOnConsecutiveCalls(
|
->willReturnOnConsecutiveCalls(
|
||||||
// SENTINEL get-master-addr-by-name svc
|
// SENTINEL get-master-addr-by-name svc
|
||||||
['127.0.0.1', '6381'],
|
['127.0.0.1', '6381'],
|
||||||
|
|
||||||
// SENTINEL slaves svc
|
// SENTINEL replicas svc
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
'name', '127.0.0.1:6382',
|
'name', '127.0.0.1:6382',
|
||||||
@@ -477,7 +477,7 @@ class SentinelReplicationTest extends PredisTestCase
|
|||||||
->withConsecutive(
|
->withConsecutive(
|
||||||
[$this->isRedisCommand('SENTINEL', ['sentinels', 'svc'])],
|
[$this->isRedisCommand('SENTINEL', ['sentinels', 'svc'])],
|
||||||
[$this->isRedisCommand('SENTINEL', ['get-master-addr-by-name', 'svc'])],
|
[$this->isRedisCommand('SENTINEL', ['get-master-addr-by-name', 'svc'])],
|
||||||
[$this->isRedisCommand('SENTINEL', ['slaves', 'svc'])]
|
[$this->isRedisCommand('SENTINEL', ['replicas', 'svc'])]
|
||||||
)
|
)
|
||||||
->willReturnOnConsecutiveCalls(
|
->willReturnOnConsecutiveCalls(
|
||||||
// SENTINEL sentinels svc
|
// SENTINEL sentinels svc
|
||||||
@@ -494,7 +494,7 @@ class SentinelReplicationTest extends PredisTestCase
|
|||||||
// SENTINEL get-master-addr-by-name svc
|
// SENTINEL get-master-addr-by-name svc
|
||||||
['127.0.0.1', '6381'],
|
['127.0.0.1', '6381'],
|
||||||
|
|
||||||
// SENTINEL slaves svc
|
// SENTINEL replicas svc
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
'name', '127.0.0.1:6382',
|
'name', '127.0.0.1:6382',
|
||||||
@@ -603,7 +603,7 @@ class SentinelReplicationTest extends PredisTestCase
|
|||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
->method('executeCommand')
|
->method('executeCommand')
|
||||||
->withConsecutive(
|
->withConsecutive(
|
||||||
[$this->isRedisCommand('SENTINEL', ['slaves', 'svc'])]
|
[$this->isRedisCommand('SENTINEL', ['replicas', 'svc'])]
|
||||||
)
|
)
|
||||||
->willReturnOnConsecutiveCalls(
|
->willReturnOnConsecutiveCalls(
|
||||||
[
|
[
|
||||||
@@ -646,7 +646,7 @@ class SentinelReplicationTest extends PredisTestCase
|
|||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
->method('executeCommand')
|
->method('executeCommand')
|
||||||
->withConsecutive(
|
->withConsecutive(
|
||||||
[$this->isRedisCommand('SENTINEL', ['slaves', 'svc'])]
|
[$this->isRedisCommand('SENTINEL', ['replicas', 'svc'])]
|
||||||
)
|
)
|
||||||
->willReturnOnConsecutiveCalls(
|
->willReturnOnConsecutiveCalls(
|
||||||
[
|
[
|
||||||
@@ -691,6 +691,69 @@ class SentinelReplicationTest extends PredisTestCase
|
|||||||
$this->assertSame('127.0.0.1:6382', (string) $slaves[0]);
|
$this->assertSame('127.0.0.1:6382', (string) $slaves[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group disconnected
|
||||||
|
*/
|
||||||
|
public function testMethodGetSlavesFallsBackToSentinelSlavesWhenReplicasIsUnknown(): void
|
||||||
|
{
|
||||||
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?role=sentinel');
|
||||||
|
$sentinel1
|
||||||
|
->expects($this->exactly(2))
|
||||||
|
->method('executeCommand')
|
||||||
|
->withConsecutive(
|
||||||
|
[$this->isRedisCommand('SENTINEL', ['replicas', 'svc'])],
|
||||||
|
[$this->isRedisCommand('SENTINEL', ['slaves', 'svc'])]
|
||||||
|
)
|
||||||
|
->willReturnOnConsecutiveCalls(
|
||||||
|
// SENTINEL replicas svc (Redis < 5.0)
|
||||||
|
new Response\Error("ERR Unknown sentinel subcommand 'replicas'"),
|
||||||
|
|
||||||
|
// SENTINEL slaves svc
|
||||||
|
[
|
||||||
|
[
|
||||||
|
'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',
|
||||||
|
],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$replication = $this->getReplicationConnection('svc', [$sentinel1]);
|
||||||
|
|
||||||
|
$slaves = $replication->getSlaves();
|
||||||
|
|
||||||
|
$this->assertCount(1, $slaves);
|
||||||
|
$this->assertSame('127.0.0.1:6382', (string) $slaves[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group disconnected
|
||||||
|
*/
|
||||||
|
public function testMethodGetSlavesDoesNotFallBackToSentinelSlavesOnOtherErrors(): void
|
||||||
|
{
|
||||||
|
$this->expectException('Predis\Response\ServerException');
|
||||||
|
$this->expectExceptionMessage('ERR No such master with that name');
|
||||||
|
|
||||||
|
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?role=sentinel');
|
||||||
|
$sentinel1
|
||||||
|
->expects($this->once())
|
||||||
|
->method('executeCommand')
|
||||||
|
->with($this->isRedisCommand(
|
||||||
|
'SENTINEL', ['replicas', 'svc']
|
||||||
|
))
|
||||||
|
->willReturn(
|
||||||
|
new Response\Error('ERR No such master with that name')
|
||||||
|
);
|
||||||
|
|
||||||
|
$replication = $this->getReplicationConnection('svc', [$sentinel1]);
|
||||||
|
|
||||||
|
$replication->getSlaves();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group disconnected
|
* @group disconnected
|
||||||
*/
|
*/
|
||||||
@@ -704,7 +767,7 @@ class SentinelReplicationTest extends PredisTestCase
|
|||||||
->expects($this->any())
|
->expects($this->any())
|
||||||
->method('executeCommand')
|
->method('executeCommand')
|
||||||
->with($this->isRedisCommand(
|
->with($this->isRedisCommand(
|
||||||
'SENTINEL', ['slaves', 'svc']
|
'SENTINEL', ['replicas', 'svc']
|
||||||
))
|
))
|
||||||
->willThrowException(
|
->willThrowException(
|
||||||
new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
|
new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
|
||||||
@@ -762,7 +825,7 @@ class SentinelReplicationTest extends PredisTestCase
|
|||||||
->expects($this->any())
|
->expects($this->any())
|
||||||
->method('executeCommand')
|
->method('executeCommand')
|
||||||
->with($this->isRedisCommand(
|
->with($this->isRedisCommand(
|
||||||
'SENTINEL', ['slaves', 'svc']
|
'SENTINEL', ['replicas', 'svc']
|
||||||
))
|
))
|
||||||
->willReturn(
|
->willReturn(
|
||||||
[
|
[
|
||||||
@@ -817,7 +880,7 @@ class SentinelReplicationTest extends PredisTestCase
|
|||||||
->expects($this->exactly(2))
|
->expects($this->exactly(2))
|
||||||
->method('executeCommand')
|
->method('executeCommand')
|
||||||
->withConsecutive(
|
->withConsecutive(
|
||||||
[$this->isRedisCommand('SENTINEL', ['slaves', 'svc'])],
|
[$this->isRedisCommand('SENTINEL', ['replicas', 'svc'])],
|
||||||
[$this->isRedisCommand('SENTINEL', ['get-master-addr-by-name', 'svc'])]
|
[$this->isRedisCommand('SENTINEL', ['get-master-addr-by-name', 'svc'])]
|
||||||
)
|
)
|
||||||
->willReturnOnConsecutiveCalls(
|
->willReturnOnConsecutiveCalls(
|
||||||
@@ -1209,7 +1272,7 @@ class SentinelReplicationTest extends PredisTestCase
|
|||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
->method('executeCommand')
|
->method('executeCommand')
|
||||||
->withConsecutive(
|
->withConsecutive(
|
||||||
[$this->isRedisCommand('SENTINEL', ['slaves', 'svc'])]
|
[$this->isRedisCommand('SENTINEL', ['replicas', 'svc'])]
|
||||||
)
|
)
|
||||||
->willReturnOnConsecutiveCalls(
|
->willReturnOnConsecutiveCalls(
|
||||||
[
|
[
|
||||||
@@ -1309,7 +1372,7 @@ class SentinelReplicationTest extends PredisTestCase
|
|||||||
->expects($this->any())
|
->expects($this->any())
|
||||||
->method('executeCommand')
|
->method('executeCommand')
|
||||||
->with($this->isRedisCommand(
|
->with($this->isRedisCommand(
|
||||||
'SENTINEL', ['slaves', 'svc']
|
'SENTINEL', ['replicas', 'svc']
|
||||||
))
|
))
|
||||||
->willReturn(
|
->willReturn(
|
||||||
[
|
[
|
||||||
@@ -1398,7 +1461,7 @@ class SentinelReplicationTest extends PredisTestCase
|
|||||||
->expects($this->any())
|
->expects($this->any())
|
||||||
->method('executeCommand')
|
->method('executeCommand')
|
||||||
->with($this->isRedisCommand(
|
->with($this->isRedisCommand(
|
||||||
'SENTINEL', ['slaves', 'svc']
|
'SENTINEL', ['replicas', 'svc']
|
||||||
))
|
))
|
||||||
->willReturn(
|
->willReturn(
|
||||||
[
|
[
|
||||||
@@ -1923,7 +1986,7 @@ class SentinelReplicationTest extends PredisTestCase
|
|||||||
->withConsecutive(
|
->withConsecutive(
|
||||||
[$this->isRedisCommand('SENTINEL', ['sentinels', 'srv'])],
|
[$this->isRedisCommand('SENTINEL', ['sentinels', 'srv'])],
|
||||||
[$this->isRedisCommand('SENTINEL', ['get-master-addr-by-name', 'srv'])],
|
[$this->isRedisCommand('SENTINEL', ['get-master-addr-by-name', 'srv'])],
|
||||||
[$this->isRedisCommand('SENTINEL', ['slaves', 'srv'])]
|
[$this->isRedisCommand('SENTINEL', ['replicas', 'srv'])]
|
||||||
)
|
)
|
||||||
->willReturnOnConsecutiveCalls(
|
->willReturnOnConsecutiveCalls(
|
||||||
// SENTINEL sentinels srv
|
// SENTINEL sentinels srv
|
||||||
@@ -1938,7 +2001,7 @@ class SentinelReplicationTest extends PredisTestCase
|
|||||||
],
|
],
|
||||||
// SENTINEL get-master-addr-by-name srv
|
// SENTINEL get-master-addr-by-name srv
|
||||||
['127.0.0.1', '6381'],
|
['127.0.0.1', '6381'],
|
||||||
// SENTINEL slaves srv
|
// SENTINEL replicas srv
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -2159,7 +2222,7 @@ class SentinelReplicationTest extends PredisTestCase
|
|||||||
->expects($this->any())
|
->expects($this->any())
|
||||||
->method('executeCommand')
|
->method('executeCommand')
|
||||||
->with($this->isRedisCommand(
|
->with($this->isRedisCommand(
|
||||||
'SENTINEL', ['slaves', 'svc']
|
'SENTINEL', ['replicas', 'svc']
|
||||||
))
|
))
|
||||||
->willReturn(
|
->willReturn(
|
||||||
[
|
[
|
||||||
|
|||||||
Reference in new issue
Block a user