-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
303 additions
and
1 deletion.
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
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,54 @@ | ||
<?php | ||
|
||
namespace Retry\BackOff; | ||
|
||
class LinearBackOffContext implements BackOffContextInterface | ||
{ | ||
private $seed; | ||
private $delta; | ||
private $max; | ||
|
||
private $interval; | ||
|
||
public function __construct($seed, $delta, $max) | ||
{ | ||
$this->seed = max(1, (int) $seed); | ||
$this->delta = max(1, (int) $delta); | ||
$this->max = max(1, (int) $max); | ||
|
||
$this->interval = $this->seed; | ||
} | ||
|
||
public function getIntervalAndIncrement() | ||
{ | ||
$interval = $this->interval; | ||
|
||
if ($interval > $this->max) { | ||
$interval = $this->max; | ||
} else { | ||
$this->interval = $this->getNextInterval(); | ||
} | ||
|
||
return $interval; | ||
} | ||
|
||
public function getInterval() | ||
{ | ||
return $this->interval; | ||
} | ||
|
||
public function resetInterval() | ||
{ | ||
$this->interval = $this->seed; | ||
} | ||
|
||
public function getNextInterval() | ||
{ | ||
return $this->interval + $this->delta; | ||
} | ||
|
||
public function getDelta() | ||
{ | ||
return $this->delta; | ||
} | ||
} |
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,179 @@ | ||
<?php | ||
|
||
namespace Retry\BackOff; | ||
|
||
use Retry\RetryContextInterface; | ||
|
||
/** | ||
* Implementation of {@link BackOffPolicyInterface} that linearly increases the back-off period for each retry attempt in a given set. | ||
*/ | ||
class LinearBackOffPolicy extends AbstractBackOffPolicy | ||
{ | ||
/** | ||
* The default initial interval value - 100 ms. | ||
* | ||
* @var int | ||
*/ | ||
const DEFAULT_INITIAL_INTERVAL = 1000; | ||
|
||
/** | ||
* The default maximum back-off time (30 seconds). | ||
* | ||
* @var int | ||
*/ | ||
const DEFAULT_MAX_INTERVAL = 30000; | ||
|
||
/** | ||
* The default delta value (1 second). | ||
* | ||
* @var float | ||
*/ | ||
const DEFAULT_DELTA_INTERVAL = 1000; | ||
|
||
/** | ||
* The initial sleep interval. | ||
* | ||
* @var int | ||
*/ | ||
private $initialInterval; | ||
|
||
/** | ||
* The maximum value of the back-off period in milliseconds. | ||
* | ||
* @var int | ||
*/ | ||
private $maxInterval; | ||
|
||
/** | ||
* The value to linearly increment the seed with for each retry attempt. | ||
* | ||
* @var float | ||
*/ | ||
private $deltaInterval; | ||
|
||
/** | ||
* @var SleeperInterface | ||
*/ | ||
private $sleeper; | ||
|
||
/** | ||
* @param int $initialInterval The initial sleep interval value. Default is 100 ms. | ||
* Cannot be set to a value less than one. | ||
* @param float $deltaInterval The delta value. Default is 1000. | ||
* @param int $maxInterval The maximum back off period. Default is 30000 (30 seconds). | ||
* The value will be reset to 1 if this method is called with a value less than 1. | ||
* Set this to avoid infinite waits if backing-off a large number of times. | ||
*/ | ||
public function __construct($initialInterval = null, $deltaInterval = null, $maxInterval = null) | ||
{ | ||
if ($initialInterval === null) { | ||
$initialInterval = self::DEFAULT_INITIAL_INTERVAL; | ||
} | ||
|
||
if ($deltaInterval === null) { | ||
$deltaInterval = self::DEFAULT_DELTA_INTERVAL; | ||
} | ||
|
||
if ($maxInterval === null) { | ||
$maxInterval = self::DEFAULT_MAX_INTERVAL; | ||
} | ||
|
||
$this->setInitialInterval($initialInterval); | ||
$this->setDeltaInterval($deltaInterval); | ||
$this->setMaxInterval($maxInterval); | ||
|
||
$this->sleeper = new DefaultSleeper(); | ||
} | ||
|
||
/** | ||
* The initial period to sleep on the first back-off. | ||
* | ||
* @return int The initial interval | ||
*/ | ||
public function getInitialInterval() | ||
{ | ||
return $this->initialInterval; | ||
} | ||
|
||
/** | ||
* Set the initial sleep interval value. Default is 1000 millisecond. | ||
* Cannot be set to a value less than one. | ||
* | ||
* @param int $initialInterval | ||
* @return void | ||
*/ | ||
public function setInitialInterval($initialInterval) | ||
{ | ||
$this->initialInterval = max(1, (int) $initialInterval); | ||
} | ||
|
||
/** | ||
* The delta to use to generate the next back-off interval from the last. | ||
* | ||
* @return int The delta in use | ||
*/ | ||
public function getDeltaInterval() | ||
{ | ||
return $this->deltaInterval; | ||
} | ||
|
||
/** | ||
* Set the delta interval value. Default is 1000. | ||
* | ||
* @param float $delta | ||
* @return void | ||
*/ | ||
public function setDeltaInterval($delta) | ||
{ | ||
$this->deltaInterval = max(1, (int) $delta); | ||
} | ||
|
||
/** | ||
* The maximum interval to sleep for. Defaults to 30 seconds. | ||
* | ||
* @return int The maximum interval. | ||
*/ | ||
public function getMaxInterval() | ||
{ | ||
return $this->maxInterval; | ||
} | ||
|
||
/** | ||
* Setter for maximum back-off period. Default is 30000 (30 seconds). | ||
* The value will be reset to 1 if this method is called with a value less than 1. | ||
* Set this to avoid infinite waits if backing off a large number of times. | ||
* | ||
* @param int $maxInterval | ||
* @return void | ||
*/ | ||
public function setMaxInterval($maxInterval) | ||
{ | ||
$this->maxInterval = max(1, (int) $maxInterval); | ||
} | ||
|
||
/** | ||
* @param \Retry\BackOff\SleeperInterface $sleeper | ||
* @return void | ||
*/ | ||
public function setSleeper(SleeperInterface $sleeper) | ||
{ | ||
$this->sleeper = $sleeper; | ||
} | ||
|
||
public function start(RetryContextInterface $context = null) | ||
{ | ||
return new LinearBackOffContext($this->initialInterval, $this->deltaInterval, $this->maxInterval); | ||
} | ||
|
||
/** | ||
* @param BackOffContextInterface|LinearBackOffContext $context | ||
*/ | ||
public function backOff(BackOffContextInterface $context = null) | ||
{ | ||
if (!$context instanceof LinearBackOffContext) { | ||
throw new \InvalidArgumentException('Context is expected to be an instanceof LinearBackOffContext.'); | ||
} | ||
|
||
$this->sleeper->sleep($context->getIntervalAndIncrement()); | ||
} | ||
} |
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,69 @@ | ||
<?php | ||
|
||
namespace Retry\Test\Retry\BackOff; | ||
|
||
use Retry\BackOff\LinearBackOffPolicy; | ||
use Retry\Test\BackOff\Fixtures\DummySleeper; | ||
|
||
class LinearBackOffPolicyTest extends \PHPUnit_Framework_TestCase | ||
{ | ||
/** | ||
* @var LinearBackOffPolicy | ||
*/ | ||
private $policy; | ||
|
||
/** | ||
* @var DummySleeper | ||
*/ | ||
private $sleeper; | ||
|
||
protected function setUp() | ||
{ | ||
$this->policy = new LinearBackOffPolicy(); | ||
$this->sleeper = new DummySleeper(); | ||
$this->policy->setSleeper($this->sleeper); | ||
} | ||
|
||
protected function tearDown() | ||
{ | ||
$this->policy = null; | ||
$this->sleeper = null; | ||
} | ||
|
||
public function testSingleBackOff() | ||
{ | ||
$context = $this->policy->start(); | ||
$this->policy->backOff($context); | ||
|
||
$this->assertEquals(LinearBackOffPolicy::DEFAULT_INITIAL_INTERVAL, $this->sleeper->getLastBackOff()); | ||
} | ||
|
||
public function testMaximumBackOff() | ||
{ | ||
$this->policy->setMaxInterval(50); | ||
|
||
$context = $this->policy->start(); | ||
$this->policy->backOff($context); | ||
|
||
$this->assertEquals(50, $this->sleeper->getLastBackOff()); | ||
} | ||
|
||
public function testMultiBackOff() | ||
{ | ||
$seed = 100; | ||
$delta = 10; | ||
|
||
$this->policy->setInitialInterval($seed); | ||
$this->policy->setDeltaInterval($delta); | ||
|
||
$context = $this->policy->start(); | ||
|
||
for ($x = 0; $x < 5; $x++) { | ||
$this->policy->backOff($context); | ||
$this->assertEquals($seed, $this->sleeper->getLastBackOff()); | ||
|
||
$seed += $delta; | ||
} | ||
} | ||
} | ||
|