Skip to content

Commit

Permalink
Merge branch '6.4' into 7.0
Browse files Browse the repository at this point in the history
* 6.4:
  [RateLimit] Allow to get RateLimit without consuming again
  Reintroduce peek consume test for sliding window policy
  [Validator] updated missing Polish translation
  fix typo
  • Loading branch information
nicolas-grekas committed Dec 30, 2023
2 parents 89aa704 + c32471a commit ece92bf
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 1 deletion.
8 changes: 7 additions & 1 deletion Policy/SlidingWindowLimiter.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,18 @@ public function reserve(int $tokens = 1, float $maxTime = null): Reservation
$now = microtime(true);
$hitCount = $window->getHitCount();
$availableTokens = $this->getAvailableTokens($hitCount);
if (0 === $tokens) {
$resetDuration = $window->calculateTimeForTokens($this->limit, $window->getHitCount());
$resetTime = \DateTimeImmutable::createFromFormat('U', $availableTokens ? floor($now) : floor($now + $resetDuration));

return new Reservation($now, new RateLimit($availableTokens, $resetTime, true, $this->limit));
}
if ($availableTokens >= $tokens) {
$window->add($tokens);

$reservation = new Reservation($now, new RateLimit($this->getAvailableTokens($window->getHitCount()), \DateTimeImmutable::createFromFormat('U', floor($now)), true, $this->limit));
} else {
$waitDuration = $window->calculateTimeForTokens($this->limit, max(1, $tokens));
$waitDuration = $window->calculateTimeForTokens($this->limit, $tokens);

if (null !== $maxTime && $waitDuration > $maxTime) {
// process needs to wait longer than set interval
Expand Down
32 changes: 32 additions & 0 deletions Tests/Policy/SlidingWindowLimiterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public function testConsume()
$rateLimit = $limiter->consume(10);
$this->assertTrue($rateLimit->isAccepted());
$this->assertSame(10, $rateLimit->getLimit());
$this->assertSame(0, $rateLimit->getRemainingTokens());
}

public function testWaitIntervalOnConsumeOverLimit()
Expand All @@ -76,6 +77,37 @@ public function testReserve()

// 2 over the limit, causing the WaitDuration to become 2/10th of the 12s interval
$this->assertEqualsWithDelta(12 / 5, $limiter->reserve(4)->getWaitDuration(), 1);

$limiter->reset();
$this->assertEquals(0, $limiter->reserve(10)->getWaitDuration());
}

public function testPeekConsume()
{
$limiter = $this->createLimiter();

$limiter->consume(9);

// peek by consuming 0 tokens twice (making sure peeking doesn't claim a token)
for ($i = 0; $i < 2; ++$i) {
$rateLimit = $limiter->consume(0);
$this->assertTrue($rateLimit->isAccepted());
$this->assertSame(10, $rateLimit->getLimit());
$this->assertEquals(
\DateTimeImmutable::createFromFormat('U', (string) floor(microtime(true))),
$rateLimit->getRetryAfter()
);
}

$limiter->consume();

$rateLimit = $limiter->consume(0);
$this->assertEquals(0, $rateLimit->getRemainingTokens());
$this->assertTrue($rateLimit->isAccepted());
$this->assertEquals(
\DateTimeImmutable::createFromFormat('U', (string) floor(microtime(true) + 12)),
$rateLimit->getRetryAfter()
);
}

private function createLimiter(): SlidingWindowLimiter
Expand Down

0 comments on commit ece92bf

Please sign in to comment.