Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 5.0.0 #2

Merged
merged 5 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading