Skip to content

Commit c15d76d

Browse files
committed
[RateLimiter] Allow to get RateLimit without consuming again.
1 parent 2d9fb06 commit c15d76d

File tree

4 files changed

+10
-32
lines changed

4 files changed

+10
-32
lines changed

src/Symfony/Component/RateLimiter/Policy/FixedWindowLimiter.php

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -59,33 +59,21 @@ public function reserve(int $tokens = 1, float $maxTime = null): Reservation
5959
$now = microtime(true);
6060
$availableTokens = $window->getAvailableTokens($now);
6161

62-
if (0 !== $tokens && $availableTokens > $tokens) {
62+
if ($availableTokens >= max(1, $tokens)) {
6363
$window->add($tokens, $now);
6464

6565
$reservation = new Reservation($now, new RateLimit($window->getAvailableTokens($now), \DateTimeImmutable::createFromFormat('U', floor($now)), true, $this->limit));
6666
} else {
67-
if ($availableTokens === $tokens) {
68-
$window->add($tokens, $now);
69-
}
70-
7167
$waitDuration = $window->calculateTimeForTokens(max(1, $tokens), $now);
7268

73-
if ($availableTokens !== $tokens && 0 !== $tokens && null !== $maxTime && $waitDuration > $maxTime) {
69+
if (null !== $maxTime && $waitDuration > $maxTime) {
7470
// process needs to wait longer than set interval
7571
throw new MaxWaitDurationExceededException(sprintf('The rate limiter wait time ("%d" seconds) is longer than the provided maximum time ("%d" seconds).', $waitDuration, $maxTime), new RateLimit($window->getAvailableTokens($now), \DateTimeImmutable::createFromFormat('U', floor($now + $waitDuration)), false, $this->limit));
7672
}
7773

78-
if ($availableTokens !== $tokens) {
79-
$window->add($tokens, $now);
80-
}
81-
82-
if ($availableTokens === $tokens || 0 === $tokens) {
83-
$accepted = true;
84-
} else {
85-
$accepted = false;
86-
}
74+
$window->add($tokens, $now);
8775

88-
$reservation = new Reservation($now + $waitDuration, new RateLimit($window->getAvailableTokens($now), \DateTimeImmutable::createFromFormat('U', floor($now + $waitDuration)), $accepted, $this->limit));
76+
$reservation = new Reservation($now + $waitDuration, new RateLimit($window->getAvailableTokens($now), \DateTimeImmutable::createFromFormat('U', floor($now + $waitDuration)), false, $this->limit));
8977
}
9078

9179
if (0 < $tokens) {

src/Symfony/Component/RateLimiter/Policy/SlidingWindowLimiter.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,13 @@ public function reserve(int $tokens = 1, float $maxTime = null): Reservation
8787

8888
if ($availableTokens === $tokens || 0 === $tokens) {
8989
$accepted = true;
90+
$timeToAct = $now;
9091
} else {
9192
$accepted = false;
93+
$timeToAct = $now + $waitDuration;
9294
}
9395

94-
$reservation = new Reservation($now + $waitDuration, new RateLimit($this->getAvailableTokens($window->getHitCount()), \DateTimeImmutable::createFromFormat('U', floor($now + $waitDuration)), $accepted, $this->limit));
96+
$reservation = new Reservation($timeToAct, new RateLimit($this->getAvailableTokens($window->getHitCount()), \DateTimeImmutable::createFromFormat('U', floor($now + $waitDuration)), $accepted, $this->limit));
9597
}
9698

9799
if (0 < $tokens) {

src/Symfony/Component/RateLimiter/Tests/Policy/FixedWindowLimiterTest.php

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,21 +57,6 @@ public function testConsume()
5757
$this->assertEquals($retryAfter, $rateLimit->getRetryAfter());
5858
}
5959

60-
public function testConsumeLastToken()
61-
{
62-
$now = time();
63-
$limiter = $this->createLimiter();
64-
$limiter->consume(9);
65-
66-
$rateLimit = $limiter->consume(1);
67-
$this->assertSame(0, $rateLimit->getRemainingTokens());
68-
$this->assertTrue($rateLimit->isAccepted());
69-
$this->assertEquals(
70-
\DateTimeImmutable::createFromFormat('U', $now + 60),
71-
$rateLimit->getRetryAfter()
72-
);
73-
}
74-
7560
/**
7661
* @dataProvider provideConsumeOutsideInterval
7762
*/

src/Symfony/Component/RateLimiter/Tests/Policy/SlidingWindowLimiterTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ public function testReserve()
114114

115115
// 2 over the limit, causing the WaitDuration to become 2/10th of the 12s interval
116116
$this->assertEqualsWithDelta(12 / 5, $limiter->reserve(4)->getWaitDuration(), 1);
117+
118+
$limiter->reset();
119+
$this->assertEquals(0, $limiter->reserve(10)->getWaitDuration());
117120
}
118121

119122
private function createLimiter(): SlidingWindowLimiter

0 commit comments

Comments
 (0)