orangesoft / backoff
Back-off algorithm implementation.
Requires
- php: ^8.1
- beberlei/assert: ^3.3
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.10
- php-parallel-lint/php-console-highlighter: ^1.0
- php-parallel-lint/php-parallel-lint: ^1.3
- phpbench/phpbench: ^1.2
- phpunit/phpunit: ^9.5
- psalm/plugin-phpunit: ^0.17.0
- vimeo/psalm: ^4.26
README
Back-off algorithm implementation.
Installation
You can install the latest version via Composer:
composer require orangesoft/backoff
This package requires PHP 8.1 or later.
Quick usage
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 use Orangesoft\BackOff\ExponentialBackOff; use Orangesoft\BackOff\Duration\Microseconds; use Orangesoft\BackOff\Retry\ExceptionClassifier\ExceptionClassifier; use Orangesoft\BackOff\Retry\Retry; $retry = new Retry( maxAttempts: 3, backOff: new ExponentialBackOff( baseTime: new Microseconds(1_000), capTime: new Microseconds(512_000), factor: 2.0, ), exceptionClassifier: new ExceptionClassifier( classNames: [ \RuntimeException::class, ], ), );
Use the Orangesoft\BackOff\Retry\Retry::call(callable $callback): mixed
method to wrap the business logic and call it with retry functionality:
/** @var int $result */ $result = $retry->call(static function (): int { $random = mt_rand(0, 1); if (0 === $random % 2) { throw new \RuntimeException(); } return $random; });
The following back-off strategies are available:
- Orangesoft\BackOff\CallbackBackOff
- Orangesoft\BackOff\ConstantBackOff
- Orangesoft\BackOff\DecorrelatedJitterBackOff
- Orangesoft\BackOff\ExponentialBackOff
- Orangesoft\BackOff\FibonacciBackOff
- Orangesoft\BackOff\LinearBackOff
Enable Jitter
Pass the implementation of Orangesoft\BackOff\Jitter\JitterInterface::class
to the back-off class and jitter will be enabled:
<?php use Orangesoft\BackOff\ExponentialBackOff; use Orangesoft\BackOff\Duration\Microseconds; use Orangesoft\BackOff\Jitter\EqualJitter; $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 1_000
μs and the cap time is 512_000
μs:
+---------+---------------------------+--------------------+
| attempt | exponential back-off (μs) | equal jitter (μs) |
+---------+---------------------------+--------------------+
| 1 | 1_000 | [0, 1_000] |
| 2 | 2_000 | [1_000, 2_000] |
| 3 | 4_000 | [2_000, 4_000] |
| 4 | 8_000 | [4_000, 8_000] |
| 5 | 16_000 | [8_000, 16_000] |
| 6 | 32_000 | [16_000, 32_000] |
| 7 | 64_000 | [32_000, 64_000] |
| 8 | 128_000 | [64_000, 128_000] |
| 9 | 256_000 | [128_000, 256_000] |
| 10 | 512_000 | [256_000, 512_000] |
+---------+---------------------------+--------------------+
The following jitters are available:
- Orangesoft\BackOff\Jitter\EqualJitter
- Orangesoft\BackOff\Jitter\FullJitter
- Orangesoft\BackOff\Jitter\ScatteredJitter
Read more about Back-Off and Jitter on AWS Architecture Blog.