Skip to content

Commit

Permalink
Added docs
Browse files Browse the repository at this point in the history
  • Loading branch information
denisyukphp committed Feb 3, 2021
1 parent 400ca66 commit 127affb
Showing 1 changed file with 268 additions and 0 deletions.
268 changes: 268 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
# Documentation

- [Configure backoff](#configure-backoff)
- [Enable jitter](#enable-jitter)
- [Use factory](#use-factory)
- [Sleep with backoff](#sleep-with-backoff)
- [Retry for exceptions](#retry-for-exceptions)
- [Handle limited attempts](#handle-limited-attempts)

## Configure backoff

Configure base time, cap time and max attempts. Base time is the time for calculating a Backoff algorithm, cap time is the limitation of calculations for base time, max attempts is the limit of call a backoff time generate. Cap time and max attempts are not required. By default cap time is 60 seconds and max attempts is `INF`.

```php
<?php

use Orangesoft\Backoff\Duration\Milliseconds;
use Orangesoft\Backoff\Duration\Seconds;
use Orangesoft\Backoff\Duration\DurationInterface;
use Orangesoft\Backoff\Strategy\ExponentialStrategy;
use Orangesoft\Backoff\Config\ConfigBuilder;
use Orangesoft\Backoff\Backoff;

$baseTime = new Milliseconds(1000);
$capTime = new Seconds(60);
$maxAttempts = 5;

$strategy = new ExponentialStrategy($baseTime);

$config = (new ConfigBuilder())
->setCapTime($capTime)
->setMaxAttempts($maxAttempts)
->build()
;

$backoff = new Backoff($strategy, $config);
```

Also you must choose a strategy for generating the backoff time. Available are strategies such as constant, exponential, linear and decorrelation. Then instance the Backoff with configured a strategy and a config.

```php
/** @var DurationInterface $backoffTime */
$backoffTime = $backoff->generate($attempt = 4);

// float(16000)
$backoffTime->toMilliseconds();
```

Backoff generates duration time which based on base time and choices strategy. As a result, you can work with such values of time as a second, millisecond, microsecond and nanosecond.

## Enable jitter

Enabled jitter allows to add an noise for a backoff time. This is necessary in order to make the generation of the backoff time unlike each other.

```php
<?php

use Orangesoft\Backoff\Config\ConfigBuilder;
use Orangesoft\Backoff\Jitter\EqualJitter;

$config = (new ConfigBuilder())
->setJitter(new EqualJitter())
->build()
;
```

You can use [EqualJitter](https://github.com/Orangesoft-Development/backoff/blob/main/src/Jitter/EqualJitter.php) or [FullJitter](https://github.com/Orangesoft-Development/backoff/blob/main/src/Jitter/FullJitter.php). By default jitter is disabled.

## Use factory

To easiest way to instance a Backoff is use a backoff factory. This makes configuring and instantiating the Backoff easier. Just configure base time, cap time, max attempts and pass them to the factory method:

```php
<?php

use Orangesoft\Backoff\Duration\Milliseconds;
use Orangesoft\Backoff\Duration\Seconds;
use Orangesoft\Backoff\Factory\BackoffFactory;
use Orangesoft\Backoff\Factory\ExponentialEqualJitterBackoff;
use Orangesoft\Backoff\Factory\LinearFullJitterBackoff;

$baseTime = new Milliseconds(1000);
$capTime = new Seconds(60);
$maxAttempts = 5;

$factory = new BackoffFactory();

/**
* @var ExponentialEqualJitterBackoff $backoff
*/
$backoff = $factory->getExponentialEqualJitterBackoff($baseTime, $capTime, $maxAttempts);
```

The same can be done by directly instantiating the Backoff. Cap time and max attempts are not required in the backoff factory.

```php
$baseTime = new Milliseconds(1000);

/**
* @var LinearFullJitterBackoff $backoff
*/
$backoff = new LinearFullJitterBackoff($baseTime);
```

The following the backoff factories are available:

- [ConstantBackoff](https://github.com/Orangesoft-Development/backoff/blob/main/src/Factory/ConstantBackoff.php)
- [ConstantFullJitterBackoff](https://github.com/Orangesoft-Development/backoff/blob/main/src/Factory/ConstantFullJitterBackoff.php)
- [ConstantEqualJitterBackoff](https://github.com/Orangesoft-Development/backoff/blob/main/src/Factory/ConstantEqualJitterBackoff.php)
- [DecorrelationJitterBackoff](https://github.com/Orangesoft-Development/backoff/blob/main/src/Factory/DecorrelationJitterBackoff.php)
- [ExponentialBackoff](https://github.com/Orangesoft-Development/backoff/blob/main/src/Factory/ExponentialBackoff.php)
- [ExponentialFullJitterBackoff](https://github.com/Orangesoft-Development/backoff/blob/main/src/Factory/ExponentialFullJitterBackoff.php)
- [ExponentialEqualJitterBackoff](https://github.com/Orangesoft-Development/backoff/blob/main/src/Factory/ExponentialEqualJitterBackoff.php)
- [LinearBackoff](https://github.com/Orangesoft-Development/backoff/blob/main/src/Factory/LinearBackoff.php)
- [LinearFullJitterBackoff](https://github.com/Orangesoft-Development/backoff/blob/main/src/Factory/LinearFullJitterBackoff.php)
- [LinearEqualJitterBackoff](https://github.com/Orangesoft-Development/backoff/blob/main/src/Factory/LinearEqualJitterBackoff.php)

## Sleep with backoff

The main purpose of Backoff is that to pause certain parts of the code for a while. This can be achieved by using a Sleeper. Just instance the Sleeper with some Backoff instance:

```php
<?php

use Orangesoft\Backoff\Duration\Milliseconds;
use Orangesoft\Backoff\Factory\ExponentialBackoff;
use Orangesoft\Backoff\Sleeper\ExponentialSleeper;
use Orangesoft\Backoff\Sleeper\Sleeper;

$baseTime = new Milliseconds(1000);
$backoff = new ExponentialBackoff($baseTime);
$sleeper = new Sleeper($backoff);

// usleep(16000000);
$sleeper->sleep($attempt = 4);
```

The exact same effect can be obtained if immediately instance the Sleeper with definitely strategy:

```php
$baseTime = new Milliseconds(1000);

$sleeper = new ExponentialSleeper($baseTime);

// usleep(16000000);
$sleeper->sleep($attempt = 4);
```

The Sleeper falls asleep with microsecond precision.

## Retry for exceptions

You can retry to any exceptions and put a backoff time before the next call but before it you must configure a retry tool where must to set max attempts, a sleeper and a exception classifier. By default max attempts is 5, the sleeper is disabled and the exception classifier catch all exceptions. See below how configure the retry tool:

```php
<?php

use Orangesoft\Backoff\Duration\Milliseconds;
use Orangesoft\Backoff\Sleeper\ConstantSleeper;
use Orangesoft\Backoff\Retry\ExceptionClassifier\ExceptionClassifier;
use Orangesoft\Backoff\Retry\RetryBuilder;
use Orangesoft\Backoff\Retry\RetryInterface;

$baseTime = new Milliseconds(1000);

$sleeper = new ConstantSleeper($baseTime);

$exceptionClassifier = new ExceptionClassifier([
\RuntimeException::class,
]);

/** @var RetryInterface $retry */
$retry = (new RetryBuilder())
->setMaxAttempts(5)
->setSleeper($sleeper)
->setExceptionClassifier($exceptionClassifier)
->build()
;
```

The retry tool interface is very similar to `call_user_func_array()` in that its method `call()` also accepts a callable and args.

```php
/**
* @param int $min
* @param int $max
*
* @return int
*
* @throws \RuntimeException
*/
$callback = function (int $min, int $max): int {
$random = mt_rand($min, $max);

if (0 === $random % 2) {
throw new \RuntimeException();
}

return $random;
};

$args = [5, 10];

$retry->call($callback, $args);
```

Retry will try to call the callable with args equal to the number set in max attempts in the config and it will put a backoff time each times for current attempt.

## Handle limited attempts

For a Backoff you can set max attempts and when this number is exceeded, a LimitedAttemptsException will be thrown:

```php
<?php

use Orangesoft\Backoff\Duration\Milliseconds;
use Orangesoft\Backoff\Duration\Seconds;
use Orangesoft\Backoff\Factory\ExponentialBackoff;
use Orangesoft\Backoff\Sleeper\Sleeper;
use Orangesoft\Backoff\Retry\RetryBuilder;
use Orangesoft\Backoff\Exception\LimitedAttemptsException;

$baseTime = new Milliseconds(1000);
$capTime = new Seconds(60);
$maxAttempts = 5;

$backoff = new ExponentialBackoff($baseTime, $capTime, $maxAttempts);

try {
$backoff->generate($attempt = 10);
} catch (LimitedAttemptsException $e) {
// ...
}
```

It works exactly the same for a Sleeper:

```php
$sleeper = new Sleeper($backoff);

try {
for ($i = 0; $i < 10; $i++) {
$sleeper->sleep($i);
}
} catch (LimitedAttemptsException $e) {
// ...
}
```

For a Retry you can set the max attempts to `PHP_INT_MAX` to disable max attempts for a retry tool and turn on count attempts of the Sleeper:

```php
$retry = (new RetryBuilder())
->setMaxAttempts(PHP_INT_MAX)
->setSleeper($sleeper)
->build()
;

try {
$retry->call(function () {
throw new \RuntimeException();
});
} catch (LimitedAttemptsException $e) {
// ...
}
```

By default max attempts of the retry tool is 5. To disable it, you need to set the largest number that supports PHP.

0 comments on commit 127affb

Please sign in to comment.