Fixed unexpected behavior in retry budget for hyperf/retry. (#2693)

* fix: retry budget bug

* fix: fix travis

* Update CHANGELOG-2.0.md

Co-authored-by: 李铭昕 <715557344@qq.com>
This commit is contained in:
谷溪 2020-10-21 15:09:25 +08:00 committed by GitHub
parent 9da3463905
commit 61624519fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 3 deletions

View File

@ -8,6 +8,7 @@
- [#2680](https://github.com/hyperf/hyperf/pull/2680) Fixed Type error for `CastsValue`, because `$isSynchronized` don't have default value. - [#2680](https://github.com/hyperf/hyperf/pull/2680) Fixed Type error for `CastsValue`, because `$isSynchronized` don't have default value.
- [#2680](https://github.com/hyperf/hyperf/pull/2680) Fixed default value in `$items` will be replaced by `__construct` for `CastsValue`. - [#2680](https://github.com/hyperf/hyperf/pull/2680) Fixed default value in `$items` will be replaced by `__construct` for `CastsValue`.
- [#2693](https://github.com/hyperf/hyperf/pull/2693) Fixed unexpected behavior in retry budget for `hyperf/retry`.
- [#2695](https://github.com/hyperf/hyperf/pull/2695) Fixed method `Container::define()` does not works when the class has been resolved. - [#2695](https://github.com/hyperf/hyperf/pull/2695) Fixed method `Container::define()` does not works when the class has been resolved.
## Optimized ## Optimized

View File

@ -42,11 +42,17 @@ class RetryBudget implements RetryBudgetInterface
*/ */
private $timerId; private $timerId;
/**
* @var float|int
*/
private $maxToken;
public function __construct(int $ttl, int $minRetriesPerSec, float $percentCanRetry) public function __construct(int $ttl, int $minRetriesPerSec, float $percentCanRetry)
{ {
$this->ttl = $ttl; $this->ttl = $ttl;
$this->minRetriesPerSec = $minRetriesPerSec; $this->minRetriesPerSec = $minRetriesPerSec;
$this->percentCanRetry = $percentCanRetry; $this->percentCanRetry = $percentCanRetry;
$this->maxToken = ($this->minRetriesPerSec / $this->percentCanRetry) * $this->ttl;
$this->budget = new SplQueue(); $this->budget = new SplQueue();
} }
@ -70,9 +76,7 @@ class RetryBudget implements RetryBudgetInterface
for ($i = 0; $i < $this->minRetriesPerSec / $this->percentCanRetry; ++$i) { for ($i = 0; $i < $this->minRetriesPerSec / $this->percentCanRetry; ++$i) {
$this->produce(); $this->produce();
} }
while (! $this->budget->isEmpty() while ($this->hasOverflown()) {
&& $this->budget->top() <= microtime(true)
) {
$this->budget->dequeue(); $this->budget->dequeue();
} }
}); });
@ -98,4 +102,10 @@ class RetryBudget implements RetryBudgetInterface
$t = microtime(true) + $this->ttl; $t = microtime(true) + $this->ttl;
$this->budget->push($t); $this->budget->push($t);
} }
public function hasOverflown(): bool
{
return (! $this->budget->isEmpty() && $this->budget->bottom() <= microtime(true))
|| $this->budget->count() > $this->maxToken;
}
} }

View File

@ -68,5 +68,20 @@ class RetryBudgetTest extends TestCase
$this->assertTrue($budget->consume()); $this->assertTrue($budget->consume());
$this->assertTrue($budget->consume()); $this->assertTrue($budget->consume());
$this->assertTrue(! $budget->consume()); $this->assertTrue(! $budget->consume());
// Retry budget should never have more than 1 token in this test
$budget = new RetryBudget(
1,
1,
1
);
$budget->init();
$ref = new \ReflectionClass(RetryBudget::class);
$prop = $ref->getProperty('budget');
$prop->setAccessible(true);
System::sleep(1.2);
$this->assertLessThanOrEqual(1, $prop->getValue($budget)->count());
System::sleep(1.2);
$this->assertLessThanOrEqual(1, $prop->getValue($budget)->count());
} }
} }