PHP code example of crowdstar / exponential-backoff
1. Go to this page and download the library: Download crowdstar/exponential-backoff library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
crowdstar / exponential-backoff example snippets
use CrowdStar\Backoff\EmptyValueCondition;
use CrowdStar\Backoff\ExponentialBackoff;
$result = (new ExponentialBackoff(new EmptyValueCondition()))->run(
function () {
return MyClass::fetchData();
}
);
use CrowdStar\Backoff\ExceptionBasedCondition;
use CrowdStar\Backoff\ExponentialBackoff;
// Allow to catch multiple types of exceptions.
$backoff = new ExponentialBackoff(new ExceptionBasedCondition(LogicException::class, RuntimeException::class));
try {
$result = $backoff->run(
function () {
return MyClass::fetchData();
}
);
} catch (Throwable $t) {
// Handle the errors here.
}
use CrowdStar\Backoff\ExceptionBasedCondition;
use CrowdStar\Backoff\ExponentialBackoff;
// Retry any HttpException -- a 503 or a timeout is worth another attempt -- but give up on a 400 right away, since
// sending the same bad request again will fail the same way.
$condition = (new ExceptionBasedCondition(HttpException::class))
->setIgnoredExceptions(HttpBadRequestException::class);
$result = (new ExponentialBackoff($condition))->run(
function () {
return MyClass::fetchData();
}
);
use CrowdStar\Backoff\AbstractRetryCondition;
use CrowdStar\Backoff\ExponentialBackoff;
$backoff = new ExponentialBackoff(
new class extends AbstractRetryCondition {
public function throwable(): bool
{
return false;
}
public function shouldRetry(mixed $result, ?Exception $e): bool
{
return ($e instanceof Exception);
}
}
);
$backoff->run(
function () {
return MyClass::fetchData();
}
);
use CrowdStar\Backoff\ExponentialBackoff;
$result = ExponentialBackoff::when(fn (mixed $result): bool => empty($result))->run(
function () {
return MyClass::fetchData();
}
);
use CrowdStar\Backoff\ExponentialBackoff;
// Retry when a \RuntimeException was thrown, and don't throw it out when the last attempt still fails.
$backoff = ExponentialBackoff::when(
fn (mixed $result, ?Exception $e): bool => ($e instanceof RuntimeException),
false
);
$result = $backoff->run(
function () {
return MyClass::fetchData();
}
);
use CrowdStar\Backoff\AbstractRetryCondition;
use CrowdStar\Backoff\ExponentialBackoff;
final class UntilRateLimitLifts extends AbstractRetryCondition
{
public function shouldRetry(mixed $result, ?Exception $e): bool
{
return ($result?->getStatusCode() === 429);
}
}
$result = (new ExponentialBackoff(new UntilRateLimitLifts()))->run(
function () {
return MyClass::fetchData();
}
);
use CrowdStar\Backoff\EmptyValueCondition;
use CrowdStar\Backoff\ExceptionBasedCondition;
use CrowdStar\Backoff\ExponentialBackoff;
use CrowdStar\Backoff\Jitter;
$backoff = new ExponentialBackoff(new EmptyValueCondition());
$backoff = new ExponentialBackoff(new ExceptionBasedCondition());
$backoff = new ExponentialBackoff(new ExceptionBasedCondition(LogicException::class, RuntimeException::class));
$backoff = ExponentialBackoff::when(fn (mixed $result, ?Exception $e): bool => ($e instanceof Exception));
$backoff
->setInitialDelay(1_000_000) // Wait up to about 1 second before the first retry; jitter decides.
->setInitialDelay(ExponentialBackoff::DEFAULT_INITIAL_DELAY)
->setMaxAttempts(3)
->setMaxAttempts(4)
->setMaxDelay(5_000_000) // Wait at most 5 seconds between two attempts.
->setMaxDelay(ExponentialBackoff::DEFAULT_MAX_DELAY)
->setMaxElapsedTime(2_000_000) // Give the whole run 2 seconds, however many attempts fit inside it.
->setMaxElapsedTime(null) // No budget at all. The default.
->setJitter(Jitter::Equal) // Wait at least half of the calculated delay, and randomly up to all of it.
->setJitter(Jitter::None) // Wait exactly as long as calculated; predictable, but no protection from collisions.
->setJitter(Jitter::Full); // Wait anywhere between nothing and the calculated delay. The default.
$result = $backoff->run(
function () {
return MyClass::fetchData();
}
);
use CrowdStar\Backoff\EmptyValueCondition;
use CrowdStar\Backoff\ExponentialBackoff;
use CrowdStar\Backoff\Mode;
// Never wait with Swoole's coroutine sleep, even inside a coroutine.
$backoff = new ExponentialBackoff(new EmptyValueCondition(), Mode::Blocking);
// Wait non-blockingly wherever a coroutine is running -- which is what happens anyway, so this is the same as
// passing nothing at all.
$backoff = new ExponentialBackoff(new EmptyValueCondition(), Mode::Swoole);
$backoff->getMode(); // Mode::Swoole or Mode::Blocking, whichever the next wait would use.
use CrowdStar\Backoff\EmptyValueCondition;
use CrowdStar\Backoff\ExponentialBackoff;
use CrowdStar\Backoff\Jitter;
$slept = [];
$backoff = (new ExponentialBackoff(new EmptyValueCondition()))
->setJitter(Jitter::None)
->setSleeper(function (int $microSeconds) use (&$slept): void {
$slept[] = $microSeconds;
});
$backoff->run(function () { return MyClass::fetchData(); });
// $slept is now [250000, 500000, 1000000], and the test took no time at all.
$result = MyClass::fetchData();
use CrowdStar\Backoff\EmptyValueCondition;
use CrowdStar\Backoff\ExponentialBackoff;
$backoff = new ExponentialBackoff(new EmptyValueCondition());
$backoff->disable();
$result = $backoff->run(function () {return MyClass::fetchData();});
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();});
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.