PHPackages                             fostam/retry - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. fostam/retry

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

fostam/retry
============

Retry any callable until success or max retries, using various delay policies

v2.0.0(11mo ago)0179MITPHPPHP ^8.2

Since Oct 19Pushed 11mo ago1 watchersCompare

[ Source](https://github.com/fostam/php-retry)[ Packagist](https://packagist.org/packages/fostam/retry)[ RSS](/packages/fostam-retry/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (5)Dependencies (1)Versions (6)Used By (0)

fostam/retry
============

[](#fostamretry)

With *Retry*, you can repeat the execution of any callable until it either succeeds, or the maximum number of attempts has been reached. Several delay policies are available for determining the sleep time between the attempts.

Features
--------

[](#features)

- Simple usage
- Different delay strategies
- Works with any PHP Callable
- No dependencies

Install
-------

[](#install)

The easiest way to install Retry is by using [composer](https://getcomposer.org/):

```
$> composer require fostam/retry

```

Usage
-----

[](#usage)

```
try {
    // sleep 1 second between attempts
    $funcResult = Retry::onFailure('myfunc', 3, new ConstantDelayPolicy(1000));
}
catch (RetryLimitException $e) {
    // failed after maximum number of attempts
}

// success before maximum number of attempts have been exceeded
```

Payload Callables
-----------------

[](#payload-callables)

Payload callables can be functions, class/object methods or closures, as listed in the [PHP documentation](https://www.php.net/manual/en/language.types.callable.php).

### Failure Condition

[](#failure-condition)

Payload callables are considered to have failed if they either throw an `Exception` or return `false`. If `false` is a legitimate result of your callable, use `onException()` instead of `onFailure()`, in which case the return value of the callable will be ignored.

The original exception that was thrown in the payload callable is chained to the `RetryLimitException`and can be retrieved via `$e->getPrevious()`.

You can also use the `onCondition()` method and pass a validation callable that takes the result of the payload callable as argument and returns `true` or `false` to indicate whether the original callable failed or not:

```
$password = 'secret';
Retry::onCondition('getInput', function($result) use ($password) {
    return $result === $password;
}, 3);
```

### Passing Parameters

[](#passing-parameters)

If you use a function or a class/object method as callable and need to pass parameters, you can wrap the call with a closure:

```
private function multiply($a, $b) {
    return $a * $b;
}

...

$x = 3;
$y = 4;
Retry::onFailure(function() use ($x, $y) {
    return $this->multiply($x, $y);
}, 3);
```

Delay Policies
--------------

[](#delay-policies)

*Retry* sleeps between two payload calls. There are multiple policies available to determine the time period of the delay. All numerical values for delay policies are interpreted as milliseconds (ms).

### Constant Sleep Value

[](#constant-sleep-value)

```
// sleep 2000 milliseconds (i.e. 2 seconds) between attempts
$policy = new ConstantDelayPolicy(2000);
```

### Linear Sleep Value Increase

[](#linear-sleep-value-increase)

```
// sleep 1 second after the first, 2 after the second, 3 after the third...
$policy = new LinearDelayPolicy(1000);
```

### Exponential Sleep Value Increase

[](#exponential-sleep-value-increase)

```
// sleep 1, 2, 4, 8, 16, ...
$policy = new ExponentialDelayPolicy(1000);

// sleep 1, 3, 9, 27, ...
$policy = new ExponentialDelayPolicy(1000, 3);
```

### Fixed Series of Sleep Values

[](#fixed-series-of-sleep-values)

```
// sleep 2, 2, 4, 20, 20, 20, 20 ... (stick to last value after series has ended)
$policy = new SeriesDelayPolicy([2000, 2000, 4000, 20000]);

// sleep 2, 2, 4, 20, 2, 2, 4, 20, 2, 2, 4, ... (repeat series after it has ended)
$policy = new SeriesDelayPolicy([2000, 2000, 4000, 20000], true);
```

### Sleep with Random Jitter

[](#sleep-with-random-jitter)

```
// sleep a random amount between 1900 and 2100 milliseconds
$policy = new JitterDelayPolicy(2000, 100);
```

### No Sleep

[](#no-sleep)

```
// don't sleep at all
$policy = new NoneDelayPolicy();
```

Advanced Features
-----------------

[](#advanced-features)

### Omitting Delay Policy

[](#omitting-delay-policy)

In case you do not want any delay between the attempts, you can either use the `NoneDelayPolicy` as described above, pass `NULL` as Delay Policy, or omit the Delay Policy argument at all:

```
// retry without delay
Retry::onFailure('myfunc', 3);
```

### Getting the Number of Attempts

[](#getting-the-number-of-attempts)

If you need to get the number of attempts that were necessary for a successful payload call, e.g. for logging purposes, you can pass a variable by reference to the `onFailure()`, `onException()` and `onCondition()`methods:

```
Retry::onFailure('myfunc', 3, null, $tries);
print "success after {$tries} attempts";
```

### Abort the Retry Loop

[](#abort-the-retry-loop)

To abort the retry loop without signalling "success", an `AbortException` can be thrown from inside the payload function.

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance51

Moderate activity, may be stable

Popularity10

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity70

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~422 days

Total

5

Last Release

348d ago

Major Versions

v1.1.0 → v2.0.02025-06-04

PHP version history (3 changes)v1.0.0PHP &gt;=7.2

v1.1.0PHP &gt;=7.4

v2.0.0PHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/4c32c6b8631d5c8b6e67cd67499be6106fe0298715cf74a38554e6608e140492?d=identicon)[fostam](/maintainers/fostam)

---

Top Contributors

[![Stammido](https://avatars.githubusercontent.com/u/123233799?v=4)](https://github.com/Stammido "Stammido (10 commits)")

---

Tags

retryrepeatdelay

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/fostam-retry/health.svg)

```
[![Health](https://phpackages.com/badges/fostam-retry/health.svg)](https://phpackages.com/packages/fostam-retry)
```

###  Alternatives

[tplaner/when

Date/Calendar recursion library.

5261.0M5](/packages/tplaner-when)[vkartaviy/retry

The library for repeatable and retryable operations

29227.2k2](/packages/vkartaviy-retry)[tobion/retry

A generic library to retry an operation in case of an error. You can configure the behavior like the exceptions to retry on.

16396.8k](/packages/tobion-retry)[mvo/contao-group-widget

Adds a new group widget that allows repeating a set of DCA fields.

28124.3k31](/packages/mvo-contao-group-widget)[yriveiro/php-backoff

Simple backoff / retry functionality

2675.1k1](/packages/yriveiro-php-backoff)[clue/connection-manager-extra

Extra decorators for creating async TCP/IP connections, built on top of ReactPHP's Socket component

2213.8k6](/packages/clue-connection-manager-extra)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
