mirror of
https://github.com/predis/predis.git
synced 2026-08-25 14:59:37 +00:00
154 lines
4.4 KiB
PHP
154 lines
4.4 KiB
PHP
<?php
|
|
|
|
/*
|
|
* This file is part of the Predis package.
|
|
*
|
|
* (c) 2009-2020 Daniele Alessandri
|
|
* (c) 2021-2026 Till Krüss
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Predis\Retry;
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
use Predis\Connection\ConnectionException;
|
|
use Predis\Connection\NodeConnectionInterface;
|
|
use Predis\Connection\Resource\Exception\StreamInitException;
|
|
use Predis\Retry\Strategy\EqualBackoff;
|
|
use Predis\Retry\Strategy\ExponentialBackoff;
|
|
use Predis\Retry\Strategy\NoBackoff;
|
|
use Predis\Retry\Strategy\RetryStrategyInterface;
|
|
use RuntimeException;
|
|
use Throwable;
|
|
|
|
class RetryTest extends TestCase
|
|
{
|
|
/**
|
|
* @group disconnected
|
|
* @dataProvider strategyProvider
|
|
* @throws Throwable
|
|
*/
|
|
public function testCallWithRetry(
|
|
RetryStrategyInterface $backoffStrategy,
|
|
int $retries,
|
|
float $expectedExecutionTime,
|
|
float $delta
|
|
) {
|
|
$retry = new Retry($backoffStrategy, $retries);
|
|
$retriesCount = 0;
|
|
|
|
$callable = static function () use (&$retriesCount, $retries) {
|
|
if ($retriesCount >= $retries) {
|
|
return;
|
|
}
|
|
|
|
++$retriesCount;
|
|
throw new StreamInitException();
|
|
};
|
|
|
|
$startTime = microtime(true);
|
|
$retry->callWithRetry($callable);
|
|
$executionTime = microtime(true) - $startTime;
|
|
|
|
$this->assertEquals($retriesCount, $retries);
|
|
$this->assertEqualsWithDelta($expectedExecutionTime, $executionTime, $delta);
|
|
|
|
$retry->updateRetriesCount(10);
|
|
$this->assertEquals(10, $retry->getRetries());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @return void
|
|
*/
|
|
public function testNoRetriesOnExcludedRetryableExceptions()
|
|
{
|
|
$retry = new Retry(new NoBackoff(), 3, [ConnectionException::class]);
|
|
$retriesCount = 0;
|
|
$callCount = 0;
|
|
|
|
$doCallable = function () use (&$callCount) {
|
|
++$callCount;
|
|
|
|
if ($callCount <= 3) {
|
|
throw new RuntimeException();
|
|
} elseif ($callCount <= 7) {
|
|
throw new ConnectionException(
|
|
$this->getMockBuilder(NodeConnectionInterface::class)->getMock()
|
|
);
|
|
}
|
|
throw new StreamInitException();
|
|
};
|
|
|
|
$failCallable = static function () use (&$retriesCount) {
|
|
++$retriesCount;
|
|
};
|
|
|
|
// Ensures that no retries happens on excluded exception.
|
|
while ($callCount < 3) {
|
|
try {
|
|
$retry->callWithRetry($doCallable, $failCallable);
|
|
} catch (Throwable $e) {
|
|
$this->assertInstanceOf(RuntimeException::class, $e);
|
|
$this->assertEquals(0, $retriesCount);
|
|
}
|
|
}
|
|
|
|
// Ensures that retries happens on specified exception.
|
|
try {
|
|
$retry->callWithRetry($doCallable, $failCallable);
|
|
} catch (Throwable $e) {
|
|
$this->assertInstanceOf(ConnectionException::class, $e);
|
|
$this->assertEquals(3, $retriesCount);
|
|
}
|
|
|
|
$retry->updateCatchableExceptions([StreamInitException::class]);
|
|
|
|
// Ensures that retries happens on updated catchable exceptions.
|
|
try {
|
|
$retry->callWithRetry($doCallable, $failCallable);
|
|
} catch (Throwable $e) {
|
|
$this->assertInstanceOf(StreamInitException::class, $e);
|
|
$this->assertEquals(6, $retriesCount);
|
|
}
|
|
|
|
$this->assertEquals(11, $callCount);
|
|
}
|
|
|
|
public function strategyProvider(): array
|
|
{
|
|
return [
|
|
'NoBackoff' => [
|
|
new NoBackoff(),
|
|
3,
|
|
1,
|
|
1,
|
|
],
|
|
'EqualBackoff' => [
|
|
new EqualBackoff(0.3 * 1000000),
|
|
3,
|
|
0.9,
|
|
0.1,
|
|
],
|
|
'ExponentialBackoff - no jitter' => [
|
|
new ExponentialBackoff(),
|
|
3,
|
|
0.112,
|
|
0.08,
|
|
],
|
|
'ExponentialBackoff - with jitter' => [
|
|
new ExponentialBackoff(
|
|
RetryStrategyInterface::DEFAULT_BASE,
|
|
RetryStrategyInterface::DEFAULT_CAP,
|
|
true
|
|
),
|
|
3,
|
|
0.112,
|
|
0.112, // Theoretically, jitter==0 might happen sequentially 3 times
|
|
],
|
|
];
|
|
}
|
|
}
|