Skip to content
Prevent overloading an unavailable service by doubling the timeout each iteration.
PHP
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
examples
src
tests
.gitignore
.travis.yml
LICENSE.txt
README.md
composer.json
phpunit.xml.dist

README.md

Build Status Latest Stable Version Latest Unstable Version License

Summary

Exponential back-offs prevent overloading an unavailable service by doubling the timeout each iteration. This class uses an exponential back-off algorithm to calculate the timeout for the next request.

Installation

composer require crowdstar/exponential-backoff:~3.0.0

Sample Usage

In following code pieces, we assume that you want to store return value of method MyClass::fetchData() in variable $result, and you want to do exponential backoff on that because something unexpected could happen when running method MyClass::fetchData().

1. Retry When Return Value Is Empty

Following code is to try to fetch some non-empty data back with method MyClass::fetchData(). This piece of code will try a few more times (by default 4) until either we get some non-empty data back, or we have reached maximum numbers of retries.

<?php
use CrowdStar\Backoff\EmptyValueCondition;
use CrowdStar\Backoff\ExponentialBackoff;

$result = (new ExponentialBackoff(new EmptyValueCondition()))->run(
    function () {
        return MyClass::fetchData();
    }
);
?>

2. Retry When Certain Exception Thrown Out

Following code is to try to fetch some data back with method MyClass::fetchData(), which may throw out exceptions. This piece of code will try a few more times (by default 4) until either we get some data back, or we have reached maximum numbers of retries.

<?php
use CrowdStar\Backoff\ExceptionBasedCondition;
use CrowdStar\Backoff\ExponentialBackoff;

$backoff = new ExponentialBackoff(new ExceptionBasedCondition(Exception::class));
try {
    $result = $backoff->run(
        function () {
            return MyClass::fetchData();
        }
    );
} catch (Exception $e) {
    // Handle the exception here.
}
?>

3. Retry When Customized Condition Met

Following code is to try to fetch some non-empty data back with method MyClass::fetchData(). This piece of code works the same as the first example, except that here it's implemented with a customized condition class instead of class \CrowdStar\Backoff\EmptyValueCondition.

<?php
use CrowdStar\Backoff\AbstractRetryCondition;
use CrowdStar\Backoff\ExponentialBackoff;

$backoff = new ExponentialBackoff(
    new class extends AbstractRetryCondition {
        public function met($result, ?Exception $e): bool
        {
            return !empty($result);
        }
    }
);
$result = $backoff->run(
    function () {
        return MyClass::fetchData();
    }
);
?>

4. More Options When Doing Exponential Backoff

Following code is to try to fetch some data back with method MyClass::fetchData(). This piece of code works the same as the second example, except that here it's implemented with a customized condition class instead of class \CrowdStar\Backoff\ExceptionBasedCondition.

In this piece of code, we also show what options are available when doing exponential backoff with the package.

<?php
use CrowdStar\Backoff\AbstractRetryCondition;
use CrowdStar\Backoff\EmptyValueCondition;
use CrowdStar\Backoff\ExceptionBasedCondition;
use CrowdStar\Backoff\ExponentialBackoff;

$backoff = new ExponentialBackoff(new EmptyValueCondition());
$backoff = new ExponentialBackoff(new ExceptionBasedCondition());
$backoff = new ExponentialBackoff(new ExceptionBasedCondition(Exception::class));
$backoff = new ExponentialBackoff(
    new class extends AbstractRetryCondition {
        public function met($result, ?Exception $e): bool
        {
            $exception = $this->getException();

            return (empty($e) || (!($e instanceof $exception)));
        }
    }
);

$backoff
    ->setType(ExponentialBackoff::TYPE_SECONDS)
    ->setType(ExponentialBackoff::TYPE_MICROSECONDS)
    ->setMaxAttempts(3)
    ->setMaxAttempts(4);

$result = $backoff->run(
    function () {
        return MyClass::fetchData();
    }
);
?>

5. To Disable Exponential Backoff Temporarily

There are two ways to disable exponential backoff temporarily for code piece like following:

<?php
$result = MyClass::fetchData();
?>

First, you may disable exponential backoff temporarily by calling method \CrowdStar\Backoff\ExponentialBackoff::disable(). For example:

<?php
use CrowdStar\Backoff\EmptyValueCondition;
use CrowdStar\Backoff\ExponentialBackoff;

$backoff = new ExponentialBackoff(new EmptyValueCondition());
$backoff->disable();
$result = $backoff->run(function () {return MyClass::fetchData();});
?>

You may also disable exponential backoff temporarily by using class \CrowdStar\Backoff\NullCondition:

<?php
use CrowdStar\Backoff\ExponentialBackoff;
use CrowdStar\Backoff\NullCondition;

$result = (new ExponentialBackoff(new NullCondition()))
    ->setRetryCondition(new NullCondition()) // The method here is for demonstration purpose.
    ->run(function () {return MyClass::fetchData();});
?>

All these 3 code piece work the same, having return value of method call MyClass::fetchData() assigned to variable $result.

Sample Scripts

Sample scripts can be found under folder examples/. Before running them under CLI, please do a composer update first:

composer update -n
You can’t perform that action at this time.