Skip to content

Commit

Permalink
Merge pull request #2 from denisyukphp/5.0.x
Browse files Browse the repository at this point in the history
  • Loading branch information
Aleksandr Denisyuk authored Jul 1, 2024
2 parents a050035 + ba3a517 commit ad139b5
Show file tree
Hide file tree
Showing 38 changed files with 497 additions and 472 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@
/psalm-baseline.xml export-ignore
/psalm.xml export-ignore
/tests/ export-ignore
/.Dockerfile export-ignore
/.Makefile export-ignore
2 changes: 2 additions & 0 deletions .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
->setRules([
'@Symfony' => true,
'@Symfony:risky' => true,
'phpdoc_separation' => false,
'phpdoc_to_comment' => false,
])
->setFinder($finder)
;
40 changes: 21 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,37 +20,37 @@ This package requires PHP 8.1 or later.

## Quick usage

Configure `Orangesoft\BackOff\Retry\BackOffRetry::class`, any of back-off classes, and `Orangesoft\BackOff\Retry\ExceptionClassifier\ExceptionClassifier::class` to retry a business logic when an exception is thrown:
Configure `Orangesoft\BackOff\Retry\Retry::class`, any of back-off classes, and `Orangesoft\BackOff\Retry\ExceptionClassifier\ExceptionClassifier::class` to retry a business logic when an exception is thrown:

```php
<?php

use Orangesoft\BackOff\ExponentialBackOff;
use Orangesoft\BackOff\Duration\Microseconds;
use Orangesoft\BackOff\Retry\ExceptionClassifier\ExceptionClassifier;
use Orangesoft\BackOff\Retry\BackOffRetry;
use Orangesoft\BackOff\Retry\Retry;

$backOffRetry = new BackOffRetry(
$retry = new Retry(
maxAttempts: 3,
baseTime: new Microseconds(1_000),
capTime: new Microseconds(10_000),
backOff: new ExponentialBackOff(
multiplier: 2.0,
baseTime: new Microseconds(1_000),
capTime: new Microseconds(512_000),
factor: 2.0,
),
exceptionClassifier: new ExceptionClassifier(
classNames: [
\Exception::class,
\RuntimeException::class,
],
),
);
```

Use the `Orangesoft\BackOff\Retry\BackOffRetry::call(callable $callback): mixed` method to wrap the business logic and call it with retry functionality:
Use the `Orangesoft\BackOff\Retry\Retry::call(callable $callback): mixed` method to wrap the business logic and call it with retry functionality:

```php
/** @var int $result */
$result = $backOffRetry->call(static function (): int {
$random = mt_rand(5, 10);
$result = $retry->call(static function (): int {
$random = mt_rand(0, 1);

if (0 === $random % 2) {
throw new \RuntimeException();
Expand All @@ -63,11 +63,11 @@ $result = $backOffRetry->call(static function (): int {
The following back-off strategies are available:

- [Orangesoft\BackOff\CallbackBackOff](./src/CallbackBackOff.php)
- [Orangesoft\BackOff\ConstantBackOff](./src/ConstantBackOff.php)
- [Orangesoft\BackOff\DecorrelatedJitterBackOff](./src/DecorrelatedJitterBackOff.php)
- [Orangesoft\BackOff\ExponentialBackOff](./src/ExponentialBackOff.php)
- [Orangesoft\BackOff\FibonacciBackOff](./src/FibonacciBackOff.php)
- [Orangesoft\BackOff\LinearBackOff](./src/LinearBackOff.php)
- [Orangesoft\BackOff\PermanentBackOff](./src/PermanentBackOff.php)

## Enable Jitter

Expand All @@ -80,19 +80,21 @@ use Orangesoft\BackOff\ExponentialBackOff;
use Orangesoft\BackOff\Duration\Microseconds;
use Orangesoft\BackOff\Jitter\EqualJitter;

$exponentialBackOff = new ExponentialBackOff(
multiplier: 2.0,
jitter: new EqualJitter(),
);

$exponentialBackOff->backOff(
attempt: 1,
$backOff = new ExponentialBackOff(
baseTime: new Microseconds(1_000),
capTime: new Microseconds(512_000),
factor: 2.0,
jitter: new EqualJitter(),
);

for ($i = 1; $i <= 10; $i++) {
$backOff->backOff(
attempt: $i,
);
}
```

Below you can see the time intervals in microseconds for exponential back-off with a multiplier of 2.0 and equal jitter, where the base time is 1000 μs and the cap time is 512000 μs:
Below you can see the time intervals in microseconds for exponential back-off with a multiplier of `2.0` and equal jitter, where the base time is `1_000` μs and the cap time is `512_000` μs:

```text
+---------+---------------------------+--------------------+
Expand Down
9 changes: 4 additions & 5 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="4.30.0@d0bc6e25d89f649e4f36a534f330f8bb4643dd69">
<file src="src/Retry/BackOffRetry.php">
<InvalidReturnType occurrences="1">
<code>mixed</code>
</InvalidReturnType>
</file>
<file src="src/Retry/Retry.php">
<InvalidReturnType occurrences="1">
<code>mixed</code>
</InvalidReturnType>
<PossiblyNullReference occurrences="2">
<code>backOff</code>
<code>classify</code>
</PossiblyNullReference>
</file>
</files>
11 changes: 9 additions & 2 deletions src/BackOff.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,23 @@
abstract class BackOff implements BackOffInterface
{
public function __construct(
private Duration $baseTime,
private Duration $capTime,
private GeneratorInterface $generator,
private SleeperInterface $sleeper,
) {
}

public function backOff(int $attempt, Duration $baseTime, Duration $capTime): void
public function backOff(int $attempt): void
{
Assertion::greaterThan($attempt, 0); // @codeCoverageIgnore

$sleepTime = $this->generator->generate($attempt, $baseTime->asNanoseconds(), $capTime->asNanoseconds());
$sleepTime = $this->generator->generate(
attempt: $attempt,
baseTime: $this->baseTime->asNanoseconds(),
capTime: $this->capTime->asNanoseconds(),
);

$this->sleeper->sleep(new Nanoseconds($sleepTime));
}
}
4 changes: 1 addition & 3 deletions src/BackOffInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

namespace Orangesoft\BackOff;

use Orangesoft\BackOff\Duration\Duration;

interface BackOffInterface
{
public function backOff(int $attempt, Duration $baseTime, Duration $capTime): void;
public function backOff(int $attempt): void;
}
6 changes: 2 additions & 4 deletions src/CallbackBackOff.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

namespace Orangesoft\BackOff;

use Orangesoft\BackOff\Duration\Duration;

/**
* @codeCoverageIgnore
*/
Expand All @@ -16,8 +14,8 @@ public function __construct(
) {
}

public function backOff(int $attempt, Duration $baseTime, Duration $capTime): void
public function backOff(int $attempt): void
{
($this->callback)($attempt, $baseTime, $capTime);
($this->callback)($attempt);
}
}
30 changes: 30 additions & 0 deletions src/ConstantBackOff.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Orangesoft\BackOff;

use Orangesoft\BackOff\Duration\Duration;
use Orangesoft\BackOff\Generator\Generator;
use Orangesoft\BackOff\Jitter\JitterInterface;
use Orangesoft\BackOff\Jitter\NullJitter;
use Orangesoft\BackOff\Sleeper\Sleeper;
use Orangesoft\BackOff\Sleeper\SleeperInterface;
use Orangesoft\BackOff\Strategy\ConstantStrategy;

final class ConstantBackOff extends BackOff
{
public function __construct(
Duration $baseTime,
Duration $capTime,
?JitterInterface $jitter = null,
?SleeperInterface $sleeper = null,
) {
$strategy = new ConstantStrategy();
$jitter ??= new NullJitter();
$generator = new Generator($strategy, $jitter);
$sleeper ??= new Sleeper();

parent::__construct($baseTime, $capTime, $generator, $sleeper);
}
}
13 changes: 9 additions & 4 deletions src/DecorrelatedJitterBackOff.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Orangesoft\BackOff;

use Orangesoft\BackOff\Duration\Duration;
use Orangesoft\BackOff\Generator\Generator;
use Orangesoft\BackOff\Jitter\NullJitter;
use Orangesoft\BackOff\Sleeper\Sleeper;
Expand All @@ -12,13 +13,17 @@

final class DecorrelatedJitterBackOff extends BackOff
{
public function __construct(float $multiplier, ?SleeperInterface $sleeper = null)
{
$strategy = new DecorrelatedJitterStrategy($multiplier);
public function __construct(
Duration $baseTime,
Duration $capTime,
float $factor = 3.0,
?SleeperInterface $sleeper = null,
) {
$strategy = new DecorrelatedJitterStrategy($factor);
$jitter = new NullJitter();
$generator = new Generator($strategy, $jitter);
$sleeper ??= new Sleeper();

parent::__construct($generator, $sleeper);
parent::__construct($baseTime, $capTime, $generator, $sleeper);
}
}
14 changes: 10 additions & 4 deletions src/ExponentialBackOff.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Orangesoft\BackOff;

use Orangesoft\BackOff\Duration\Duration;
use Orangesoft\BackOff\Generator\Generator;
use Orangesoft\BackOff\Jitter\JitterInterface;
use Orangesoft\BackOff\Jitter\NullJitter;
Expand All @@ -13,13 +14,18 @@

final class ExponentialBackOff extends BackOff
{
public function __construct(float $multiplier, ?JitterInterface $jitter = null, ?SleeperInterface $sleeper = null)
{
$strategy = new ExponentialStrategy($multiplier);
public function __construct(
Duration $baseTime,
Duration $capTime,
float $factor = 2.0,
?JitterInterface $jitter = null,
?SleeperInterface $sleeper = null,
) {
$strategy = new ExponentialStrategy($factor);
$jitter ??= new NullJitter();
$generator = new Generator($strategy, $jitter);
$sleeper ??= new Sleeper();

parent::__construct($generator, $sleeper);
parent::__construct($baseTime, $capTime, $generator, $sleeper);
}
}
11 changes: 8 additions & 3 deletions src/FibonacciBackOff.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Orangesoft\BackOff;

use Orangesoft\BackOff\Duration\Duration;
use Orangesoft\BackOff\Generator\Generator;
use Orangesoft\BackOff\Jitter\JitterInterface;
use Orangesoft\BackOff\Jitter\NullJitter;
Expand All @@ -13,13 +14,17 @@

final class FibonacciBackOff extends BackOff
{
public function __construct(?JitterInterface $jitter = null, ?SleeperInterface $sleeper = null)
{
public function __construct(
Duration $baseTime,
Duration $capTime,
?JitterInterface $jitter = null,
?SleeperInterface $sleeper = null,
) {
$strategy = new FibonacciStrategy();
$jitter ??= new NullJitter();
$generator = new Generator($strategy, $jitter);
$sleeper ??= new Sleeper();

parent::__construct($generator, $sleeper);
parent::__construct($baseTime, $capTime, $generator, $sleeper);
}
}
11 changes: 8 additions & 3 deletions src/LinearBackOff.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Orangesoft\BackOff;

use Orangesoft\BackOff\Duration\Duration;
use Orangesoft\BackOff\Generator\Generator;
use Orangesoft\BackOff\Jitter\JitterInterface;
use Orangesoft\BackOff\Jitter\NullJitter;
Expand All @@ -13,13 +14,17 @@

final class LinearBackOff extends BackOff
{
public function __construct(?JitterInterface $jitter = null, ?SleeperInterface $sleeper = null)
{
public function __construct(
Duration $baseTime,
Duration $capTime,
?JitterInterface $jitter = null,
?SleeperInterface $sleeper = null
) {
$strategy = new LinearStrategy();
$jitter ??= new NullJitter();
$generator = new Generator($strategy, $jitter);
$sleeper ??= new Sleeper();

parent::__construct($generator, $sleeper);
parent::__construct($baseTime, $capTime, $generator, $sleeper);
}
}
15 changes: 15 additions & 0 deletions src/NullBackOff.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Orangesoft\BackOff;

/**
* @codeCoverageIgnore
*/
final class NullBackOff implements BackOffInterface
{
public function backOff(int $attempt): void
{
}
}
25 changes: 0 additions & 25 deletions src/PermanentBackOff.php

This file was deleted.

Loading

0 comments on commit ad139b5

Please sign in to comment.