mirror of
https://github.com/predis/predis.git
synced 2026-09-15 12:57:10 +00:00
Treat LOADING Errors as Connection Failures to Retry with Next Replica (#1536)
* fix(sentinel-replication): Treat LOADING error responses as ConnectionException to allow retry mechanism to discard the current replica and switch to the next available one. * fix(sentinel-replication): add changelog entries for LOADING response handling * Update CHANGELOG.md * Update CHANGELOG.md --------- Co-authored-by: Mustafa AKBEL <mustafa.akbel@pusula.net.tr> Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
## Changelog
|
||||
|
||||
## Unreleased
|
||||
### Changed
|
||||
- Handle and retry `LOADING` errors from Sentinel replicas (#1536)
|
||||
|
||||
### Fixed
|
||||
- Fixed PHP 8.4 deprecated call to `stream_context_set_option()` (#1545)
|
||||
- Fixed return type for `ZCOUNT` to be `int` (#1547)
|
||||
|
||||
@@ -715,6 +715,9 @@ class SentinelReplication extends AbstractAggregateConnection implements Replica
|
||||
while ($retries <= $this->retryLimit) {
|
||||
try {
|
||||
$response = $this->getConnectionByCommand($command)->$method($command);
|
||||
if ($response instanceof Error && $response->getErrorType() === 'LOADING') {
|
||||
throw new ConnectionException($this->current, $response->getMessage());
|
||||
}
|
||||
break;
|
||||
} catch (CommunicationException $exception) {
|
||||
$this->wipeServerList();
|
||||
|
||||
@@ -1599,6 +1599,91 @@ class SentinelReplicationTest extends PredisTestCase
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testDiscardsSlaveWhenRespondsLOADINGAndExecutesReadOnlyCommandOnNextSlave(): void
|
||||
{
|
||||
$sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?role=sentinel');
|
||||
$sentinel1
|
||||
->expects($this->any())
|
||||
->method('executeCommand')
|
||||
->with($this->isRedisCommand(
|
||||
'SENTINEL', ['slaves', 'svc']
|
||||
))
|
||||
->willReturn(
|
||||
[
|
||||
[
|
||||
'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?role=master');
|
||||
$master
|
||||
->expects($this->any())
|
||||
->method('isConnected')
|
||||
->willReturn(true);
|
||||
|
||||
$slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?role=slave');
|
||||
$slave1
|
||||
->expects($this->any())
|
||||
->method('isConnected')
|
||||
->willReturn(true);
|
||||
$slave1
|
||||
->expects($this->once())
|
||||
->method('executeCommand')
|
||||
->with(
|
||||
$this->isRedisCommand('GET', ['key'])
|
||||
)
|
||||
->willReturn(
|
||||
new Response\Error('LOADING')
|
||||
);
|
||||
|
||||
$slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?role=slave');
|
||||
$slave2
|
||||
->expects($this->any())
|
||||
->method('isConnected')
|
||||
->willReturn(true);
|
||||
$slave2
|
||||
->expects($this->once())
|
||||
->method('executeCommand')
|
||||
->withConsecutive(
|
||||
[$this->isRedisCommand('GET', ['key'])]
|
||||
)
|
||||
->willReturnOnConsecutiveCalls(
|
||||
'value'
|
||||
);
|
||||
|
||||
/** @var Connection\FactoryInterface|MockObject */
|
||||
$factory = $this->getMockBuilder('Predis\Connection\FactoryInterface')->getMock();
|
||||
$factory
|
||||
->expects($this->once())
|
||||
->method('create')
|
||||
->with([
|
||||
'host' => '127.0.0.1',
|
||||
'port' => '6383',
|
||||
'role' => 'slave',
|
||||
])
|
||||
->willReturn($slave2);
|
||||
|
||||
$replication = $this->getReplicationConnection('svc', [$sentinel1], $factory);
|
||||
|
||||
$replication->add($master);
|
||||
$replication->add($slave1);
|
||||
|
||||
$this->assertSame('value', $replication->executeCommand(
|
||||
Command\RawCommand::create('get', 'key')
|
||||
));
|
||||
$this->assertSame($slave2, $replication->getCurrent());
|
||||
}
|
||||
|
||||
// ******************************************************************** //
|
||||
// ---- HELPER METHODS ------------------------------------------------ //
|
||||
// ******************************************************************** //
|
||||
|
||||
Reference in New Issue
Block a user