Skip to content

Commit

Permalink
Added MicroSleepErrorHandler.
Browse files Browse the repository at this point in the history
Added ExponentialBackoffErrorHandler.
Added PowersOfTwoSequence and accompanying test.
  • Loading branch information
Bilge committed Jul 11, 2016
1 parent 3081859 commit 3c570ad
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 7 deletions.
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Retry
[![Code style][Style image]][Style]

Retry provides a function to retry failing operations. An operation is deemed to have failed if it throws an exception.
This library is a rewrite of [Igor Wiedler's retry](https://github.com/igorw/retry) but aims to remain faithful to the
spirit of the original.

Requirements
------------
Expand All @@ -17,18 +19,19 @@ Requirements
Usage
-----

The `retry` function has the following signature.
The `retry` function retries an operation up to the specified number of times with an optional error handler and has
the following signature.

```
retry(int $times, callable $operation, callable $onError = null);
```
* `$times` specifies how many times the operation may be called.
* `$operation` is a callback to be run up to the specified number of times.
* `$onError` is called immediately before retrying the operation.
* `$times`—Maximum number of times the operation may run.
* `$operation`—Operation to run up to the specified number of times.
* `$onError`—Optional. Error handler called immediately before retrying the operation.

Note that in the [original library](https://github.com/igorw/retry), `$times` specified the number of *retries* and
therefore the operation could run up to `n + 1` times. In this version, `$times` specifies exactly the number of
times the operation may run such that if zero (`0`) is specified it will never run.
Note in the original library, `$times` specifies the number of *retries* and therefore the operation could run up to
`$times + 1` times. In this version, `$times` specifies exactly the number of times the operation may run such that if
zero (`0`) is specified it will not run.

### Example

Expand Down
26 changes: 26 additions & 0 deletions src/ErrorHandler/ExponentialBackoffErrorHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php
namespace ScriptFUSION\Retry\ErrorHandler;

use ScriptFUSION\Retry\Sequence\PowersOfTwoSequence;

/**
* Sleeps for an exponentially increasing series of delays.
*/
class ExponentialBackoffErrorHandler extends MicroSleepErrorHandler
{
private $microTimeCoefficient;

public function __construct($microTimeCoefficient = 102000)
{
parent::__construct($this->generateSequence(
$this->microTimeCoefficient = $microTimeCoefficient|0
));
}

private function generateSequence($coefficient)
{
foreach (new PowersOfTwoSequence as $base) {
yield $base * $coefficient;
}
}
}
22 changes: 22 additions & 0 deletions src/ErrorHandler/MicroSleepErrorHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php
namespace ScriptFUSION\Retry\ErrorHandler;

/**
* Sleeps for a series of microsecond delays for each invocation.
*/
class MicroSleepErrorHandler
{
private $delays;

public function __construct(\Iterator $delays)
{
$this->delays = $delays;
}

public function __invoke()
{
$this->delays->next();

usleep($this->delays->current());
}
}
16 changes: 16 additions & 0 deletions src/Sequence/PowersOfTwoSequence.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php
namespace ScriptFUSION\Retry\Sequence;

final class PowersOfTwoSequence implements \IteratorAggregate
{
private $power = 0;

public function getIterator()
{
yield 1;

while (0 < $value = 2 << $this->power++) {
yield $value;
}
}
}
24 changes: 24 additions & 0 deletions test/Sequence/PowersOfTwoSequenceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php
namespace ScriptFUSIONTest\Retry\Sequence;

use ScriptFUSION\Retry\Sequence\PowersOfTwoSequence;

final class PowersOfTwoSequenceTest extends \PHPUnit_Framework_TestCase
{
public function testSequence()
{
$powers = new \LimitIterator((new PowersOfTwoSequence)->getIterator(), 0, 6);

self::assertSame([1, 2, 4, 8, 16, 32], iterator_to_array($powers));
}

public function testIsFiniteSequence()
{
$counter = 0;
foreach (new \LimitIterator((new PowersOfTwoSequence)->getIterator(), 0, $limit = 100) as $_) {
++$counter;
}

self::assertLessThan($limit, $counter);
}
}

0 comments on commit 3c570ad

Please sign in to comment.