8000 [RateLimit] Allow to get RateLimit without consuming again · symfony/symfony@677b8b7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 677b8b7

Browse files
ERubannicolas-grekas
authored andcommitted
[RateLimit] Allow to get RateLimit without consuming again
1 parent 169e383 commit 677b8b7

File tree

2 files changed

+13
-3
lines changed

2 files changed

+13
-3
lines changed

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,18 @@ public function reserve(int $tokens = 1, float $maxTime = null): Reservation
6565
$now = microtime(true);
6666
$hitCount = $window->getHitCount();
6767
$availableTokens = $this->getAv 10000 ailableTokens($hitCount);
68+
if (0 === $tokens) {
69+
$resetDuration = $window->calculateTimeForTokens($this->limit, $window->getHitCount());
70+
$resetTime = \DateTimeImmutable::createFromFormat('U', $availableTokens ? floor($now) : floor($now + $resetDuration));
71+
72+
return new Reservation($now, new RateLimit($availableTokens, $resetTime, true, $this->limit));
73+
}
6874
if ($availableTokens >= $tokens) {
6975
$window->add($tokens);
7076

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

7581
if (null !== $maxTime && $waitDuration > $maxTime) {
7682
// process needs to wait longer than set interval

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public function testConsume()
5252
$rateLimit = $limiter->consume(10);
5353
$this->assertTrue($rateLimit->isAccepted());
5454
$this->assertSame(10, $rateLimit->getLimit());
55+
$this->assertSame(0, $rateLimit->getRemainingTokens());
5556
}
5657

5758
public function testWaitIntervalOnConsumeOverLimit()
@@ -76,6 +77,9 @@ public function testReserve()
7677

7778
// 2 over the limit, causing the WaitDuration to become 2/10th of the 12s interval
7879
$this->assertEqualsWithDelta(12 / 5, $limiter->reserve(4)->getWaitDuration(), 1);
80+
81+
$limiter->reset();
82+
$this->assertEquals(0, $limiter->reserve(10)->getWaitDuration());
7983
}
8084

8185
public function testPeekConsume()
@@ -90,7 +94,7 @@ public function testPeekConsume()
9094
$this->assertTrue($rateLimit->isAccepted());
9195
$this->assertSame(10, $rateLimit->getLimit());
9296
$this->assertEquals(
93-
\DateTimeImmutable::createFromFormat('U.u', sprintf('%.6F', microtime(true))),
97+
\DateTimeImmutable::createFromFormat('U', (string) floor(microtime(true))),
9498
$rateLimit->getRetryAfter()
9599
);
96100
}
@@ -101,7 +105,7 @@ public function testPeekConsume()
101105
$this->assertEquals(0, $rateLimit->getRemainingTokens());
102106
$this->assertTrue($rateLimit->isAccepted());
103107
$this->assertEquals(
104-
\DateTimeImmutable::createFromFormat('U.u', sprintf('%.6F', microtime(true) + 12)),
108+
\DateTimeImmutable::createFromFormat('U', (string) floor(microtime(true) + 12)),
105109
$rateLimit->getRetryAfter()
106110
);
107111
}

0 commit comments

Comments
 (0)
0