Added retry support (#1616)

* Initial work on retries

* Added retry class and test coverage

* Added support for standalone and cluster

* Make TimeoutException instance of CommunicationException

* Added pipeline, trasnaction, replication support

* Fixed broken test

* Marked test as relay-incompatible

* Marked test as relay-incompatible

* Fixed analysis errors, added missing tests

* Codestyle fixes

* Fixed test

* Update README.md

* Update README.md

* Update README.md

* Updated README.md

* Refactor retry on read and write

* Added check for timeout value

* Updated README.md

* Fixed README.md

* Codestyle changes

* Added missing coverage

* Added missing test coverage

* Removed comments

* Added retry support for Relay connection (#1620)

* Added integration test case with mocked retry

* Changed client initialisation in tests

* Marked test as relay-incompatible

---------

Co-authored-by: Pavlo Yatsukhnenko <yatsukhnenko@users.noreply.github.com>
This commit is contained in:
Vladyslav Vildanov
2025-12-23 10:40:46 +02:00
committed by GitHub
parent 0ae180c942
commit 980326d5d8
42 changed files with 2502 additions and 222 deletions
@@ -15,6 +15,10 @@ namespace Predis\Transaction\Strategy;
use PHPUnit\Framework\TestCase;
use Predis\Command\CommandInterface;
use Predis\Connection\NodeConnectionInterface;
use Predis\Connection\Parameters;
use Predis\Retry\Retry;
use Predis\Retry\Strategy\ExponentialBackoff;
use Predis\TimeoutException;
use Predis\Transaction\MultiExecState;
class NodeConnectionStrategyTest extends TestCase
@@ -46,8 +50,72 @@ class NodeConnectionStrategyTest extends TestCase
->with($this->mockCommand)
->willReturn('OK');
$this->mockConnection
->expects($this->any())
->method('getParameters')
->willReturn(new Parameters());
$strategy = new NodeConnectionStrategy($this->mockConnection, new MultiExecState());
$this->assertEquals('OK', $strategy->executeCommand($this->mockCommand));
}
/**
* @return void
*/
public function testUnwatch(): void
{
$this->mockConnection
->expects($this->once())
->method('executeCommand')
->with($this->callback(function ($command) {
return $command->getId() === 'UNWATCH';
}))
->willReturn('OK');
$this->mockConnection
->expects($this->any())
->method('getParameters')
->willReturn(new Parameters());
$strategy = new NodeConnectionStrategy($this->mockConnection, new MultiExecState());
$this->assertEquals('OK', $strategy->unwatch());
}
/**
* @return void
*/
public function testUnwatchWithRetries(): void
{
$parameters = new Parameters([
'retry' => new Retry(new ExponentialBackoff(1000, 10000), 3),
]);
$this->mockConnection
->expects($this->exactly(4))
->method('executeCommand')
->with($this->callback(function ($command) {
return $command->getId() === 'UNWATCH';
}))
->willReturnOnConsecutiveCalls(
$this->throwException(new TimeoutException($this->mockConnection)),
$this->throwException(new TimeoutException($this->mockConnection)),
$this->throwException(new TimeoutException($this->mockConnection)),
'OK'
);
$this->mockConnection
->expects($this->any())
->method('getParameters')
->willReturn($parameters);
$this->mockConnection
->expects($this->exactly(3))
->method('disconnect');
$strategy = new NodeConnectionStrategy($this->mockConnection, new MultiExecState());
$this->assertEquals('OK', $strategy->unwatch());
}
}