Skip to content

Commit 3081859

Browse files
committed
Added optional error handler.
1 parent 7504b97 commit 3081859

File tree

3 files changed

+46
-13
lines changed

3 files changed

+46
-13
lines changed

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,23 @@ Usage
2020
The `retry` function has the following signature.
2121

2222
```
23-
retry(int $times, callable $operation);
23+
retry(int $times, callable $operation, callable $onError = null);
2424
```
2525
* `$times` specifies how many times the operation may be called.
2626
* `$operation` is a callback to be run up to the specified number of times.
27+
* `$onError` is called immediately before retrying the operation.
2728

28-
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.
29+
Note that in the [original library](https://github.com/igorw/retry), `$times` specified the number of *retries* and
30+
therefore the operation could run up to `n + 1` times. In this version, `$times` specifies exactly the number of
31+
times the operation may run such that if zero (`0`) is specified it will never run.
2932

3033
### Example
3134

35+
The following code fragment attempts to fetch data from a URL over HTTP up to five times.
36+
3237
```php
3338
use function ScriptFUSION\Retry\retry;
3439

35-
// Try an operation up to 5 times.
3640
$response = retry(5, function () use ($url) {
3741
return HttpConnector::fetch($url);
3842
});
@@ -47,4 +51,3 @@ $response = retry(5, function () use ($url) {
4751
[Coverage image]: https://coveralls.io/repos/ScriptFUSION/Retry/badge.svg "Test coverage"
4852
[Style]: https://styleci.io/repos/62990558
4953
[Style image]: https://styleci.io/repos/62990558/shield?style=flat "Code style"
50-

src/retry.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@
22
namespace ScriptFUSION\Retry;
33

44
/**
5-
* Tries the specified operation up to the specified number of times.
5+
* Tries the specified operation up to the specified number of times. If
6+
* specified, the error handler will be called immediately before retrying the
7+
* operation.
68
*
79
* @param int $tries Number of times.
810
* @param callable $operation Operation.
11+
* @param callable $onError Optional. Error handler.
912
*
1013
* @return mixed Result of running the operation if tries is greater than zero,
1114
* otherwise null.
1215
*/
13-
function retry($tries, callable $operation)
16+
function retry($tries, callable $operation, callable $onError = null)
1417
{
1518
$tries |= 0;
1619

@@ -21,11 +24,13 @@ function retry($tries, callable $operation)
2124
try {
2225
beginning:
2326
return $operation();
24-
} catch (\Exception $e) {
27+
} catch (\Exception $exception) {
2528
if ($tries === ++$attempts) {
26-
throw new FailingTooHardException($attempts, $e);
29+
throw new FailingTooHardException($attempts, $exception);
2730
}
2831

32+
$onError && $onError($exception);
33+
2934
goto beginning;
3035
}
3136
}

test/RetryTest.php

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public function testWithoutFailing()
1010
$invocations = 0;
1111

1212
$value = \ScriptFUSION\Retry\retry($tries = 1, function () use (&$invocations) {
13-
$invocations++;
13+
++$invocations;
1414

1515
return 5;
1616
});
@@ -25,10 +25,11 @@ public function testFailingOnce()
2525
$failed = false;
2626

2727
$value = \ScriptFUSION\Retry\retry($tries = 2, function () use (&$invocations, &$failed) {
28-
$invocations++;
28+
++$invocations;
2929

3030
if (!$failed) {
3131
$failed = true;
32+
3233
throw new \RuntimeException;
3334
}
3435

@@ -45,7 +46,7 @@ public function testZeroTries()
4546
$invocations = 0;
4647

4748
$value = \ScriptFUSION\Retry\retry($tries = 0, function () use (&$invocations) {
48-
$invocations++;
49+
++$invocations;
4950

5051
return 5;
5152
});
@@ -61,14 +62,38 @@ public function testFailingTooHard()
6162

6263
try {
6364
\ScriptFUSION\Retry\retry($tries = 2, function () use (&$invocations, &$innerException) {
64-
$invocations++;
65+
++$invocations;
66+
6567
throw $innerException = new \RuntimeException;
6668
});
67-
} catch (\Exception $outerException) {
69+
} catch (FailingTooHardException $outerException) {
6870
}
6971

7072
self::assertInstanceOf(FailingTooHardException::class, $outerException);
7173
self::assertSame($innerException, $outerException->getPrevious());
7274
self::assertSame($tries, $invocations);
7375
}
76+
77+
public function testErrorCallback()
78+
{
79+
$invocations = $errors = 0;
80+
$outerException = $innerException = null;
81+
82+
try {
83+
\ScriptFUSION\Retry\retry($tries = 2, function () use (&$invocations, &$innerException) {
84+
++$invocations;
85+
86+
throw $innerException = new \RuntimeException;
87+
}, function (\Exception $exception) use (&$innerException, &$errors) {
88+
++$errors;
89+
90+
self::assertSame($innerException, $exception);
91+
});
92+
} catch (FailingTooHardException $outerException) {
93+
}
94+
95+
self::assertInstanceOf(FailingTooHardException::class, $outerException);
96+
self::assertSame($tries, $invocations);
97+
self::assertSame(1, $errors);
98+
}
7499
}

0 commit comments

Comments
 (0)