-
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added a BackOffRunner that runs code with a back off strategy.
- Loading branch information
1 parent
1fe47e1
commit c203818
Showing
2 changed files
with
109 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace EventSauce\BackOff; | ||
|
||
use Throwable; | ||
|
||
/** | ||
* # This one is for the lazy people. | ||
* | ||
* This class is introduced for extremely lazy developers that can't even be bothered | ||
* to write the tiniest amount of bootstrapping code, ever. LAZY! YOU'RE LAZY! BOOOO! | ||
*/ | ||
class BackOffRunner | ||
{ | ||
private BackOffStrategy $strategy; | ||
|
||
/** | ||
* @var class-string<Throwable> | ||
*/ | ||
private string $retryOn; | ||
|
||
/** | ||
* @param class-string<Throwable> $retryOn | ||
*/ | ||
public function __construct(BackOffStrategy $strategy, string $retryOn = Throwable::class) | ||
{ | ||
$this->strategy = $strategy; | ||
$this->retryOn = $retryOn; | ||
} | ||
|
||
/** | ||
* @return mixed | ||
* @throws Throwable | ||
*/ | ||
public function run(callable $task) | ||
{ | ||
$tries = 0; | ||
|
||
while(true) { | ||
try { | ||
return $task(); | ||
} catch (Throwable $exception) { | ||
if ( ! $exception instanceof $this->retryOn) { | ||
throw $exception; | ||
} | ||
|
||
$this->strategy->backOff(++$tries, $exception); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace EventSauce\BackOff; | ||
|
||
use Exception; | ||
use LogicException; | ||
use PHPUnit\Framework\TestCase; | ||
use Throwable; | ||
|
||
class BackOffRunnerTest extends TestCase | ||
{ | ||
/** | ||
* @test | ||
*/ | ||
public function running_a_callable_with_backoff(): void | ||
{ | ||
$runner = new BackOffRunner(new NoWaitingBackOffStrategy(5)); | ||
$tries = 0; | ||
$exception = null; | ||
|
||
try { | ||
$runner->run(function () use (&$tries) { | ||
$tries++; | ||
throw new Exception('oh no, this is terrible'); | ||
}); | ||
} catch (Throwable $throwable) { | ||
$exception = $throwable; | ||
} | ||
|
||
self::assertEquals(6, $tries); // retry 5 failures + 1 final fail | ||
self::assertEquals(new Exception('oh no, this is terrible'), $exception); | ||
} | ||
/** | ||
* @test | ||
*/ | ||
public function not_matching_the_exception_type(): void | ||
{ | ||
$runner = new BackOffRunner(new NoWaitingBackOffStrategy(5), LogicException::class); | ||
$tries = 0; | ||
$exception = null; | ||
|
||
try { | ||
$runner->run(function () use (&$tries) { | ||
$tries++; | ||
throw new Exception('oh no, this is terrible'); | ||
}); | ||
} catch (Throwable $throwable) { | ||
$exception = $throwable; | ||
} | ||
|
||
self::assertEquals(1, $tries); // retry 5 failures + 1 final fail | ||
self::assertEquals(new Exception('oh no, this is terrible'), $exception); | ||
} | ||
} |