diff --git a/src/Symfony/Component/HttpFoundation/RateLimiter/AbstractRequestRateLimiter.php b/src/Symfony/Component/HttpFoundation/RateLimiter/AbstractRequestRateLimiter.php index cf6d1e1bc3c56..f700ebcd8657c 100644 --- a/src/Symfony/Component/HttpFoundation/RateLimiter/AbstractRequestRateLimiter.php +++ b/src/Symfony/Component/HttpFoundation/RateLimiter/AbstractRequestRateLimiter.php @@ -12,9 +12,9 @@ namespace Symfony\Component\HttpFoundation\RateLimiter; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\RateLimiter\Limit; use Symfony\Component\RateLimiter\LimiterInterface; use Symfony\Component\RateLimiter\NoLimiter; +use Symfony\Component\RateLimiter\RateLimit; /** * An implementation of RequestRateLimiterInterface that @@ -26,23 +26,23 @@ */ abstract class AbstractRequestRateLimiter implements RequestRateLimiterInterface { - public function consume(Request $request): Limit + public function consume(Request $request): RateLimit { $limiters = $this->getLimiters($request); if (0 === \count($limiters)) { $limiters = [new NoLimiter()]; } - $minimalLimit = null; + $minimalRateLimit = null; foreach ($limiters as $limiter) { - $limit = $limiter->consume(1); + $rateLimit = $limiter->consume(1); - if (null === $minimalLimit || $limit->getRemainingTokens() < $minimalLimit->getRemainingTokens()) { - $minimalLimit = $limit; + if (null === $minimalRateLimit || $rateLimit->getRemainingTokens() < $minimalRateLimit->getRemainingTokens()) { + $minimalRateLimit = $rateLimit; } } - return $minimalLimit; + return $minimalRateLimit; } public function reset(Request $request): void diff --git a/src/Symfony/Component/HttpFoundation/RateLimiter/RequestRateLimiterInterface.php b/src/Symfony/Component/HttpFoundation/RateLimiter/RequestRateLimiterInterface.php index d37427760018b..c7d31ba5db015 100644 --- a/src/Symfony/Component/HttpFoundation/RateLimiter/RequestRateLimiterInterface.php +++ b/src/Symfony/Component/HttpFoundation/RateLimiter/RequestRateLimiterInterface.php @@ -12,7 +12,7 @@ namespace Symfony\Component\HttpFoundation\RateLimiter; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\RateLimiter\Limit; +use Symfony\Component\RateLimiter\RateLimit; /** * A special type of limiter that deals with requests. @@ -26,7 +26,7 @@ */ interface RequestRateLimiterInterface { - public function consume(Request $request): Limit; + public function consume(Request $request): RateLimit; public function reset(Request $request): void; } diff --git a/src/Symfony/Component/RateLimiter/CompoundLimiter.php b/src/Symfony/Component/RateLimiter/CompoundLimiter.php index 6722e0b436e70..286940930326e 100644 --- a/src/Symfony/Component/RateLimiter/CompoundLimiter.php +++ b/src/Symfony/Component/RateLimiter/CompoundLimiter.php @@ -38,18 +38,18 @@ public function reserve(int $tokens = 1, ?float $maxTime = null): Reservation throw new ReserveNotSupportedException(__CLASS__); } - public function consume(int $tokens = 1): Limit + public function consume(int $tokens = 1): RateLimit { - $minimalLimit = null; + $minimalRateLimit = null; foreach ($this->limiters as $limiter) { - $limit = $limiter->consume($tokens); + $rateLimit = $limiter->consume($tokens); - if (null === $minimalLimit || $limit->getRemainingTokens() < $minimalLimit->getRemainingTokens()) { - $minimalLimit = $limit; + if (null === $minimalRateLimit || $rateLimit->getRemainingTokens() < $minimalRateLimit->getRemainingTokens()) { + $minimalRateLimit = $rateLimit; } } - return $minimalLimit; + return $minimalRateLimit; } public function reset(): void diff --git a/src/Symfony/Component/RateLimiter/Exception/MaxWaitDurationExceededException.php b/src/Symfony/Component/RateLimiter/Exception/MaxWaitDurationExceededException.php index 025103f7a8741..1eeec9de64193 100644 --- a/src/Symfony/Component/RateLimiter/Exception/MaxWaitDurationExceededException.php +++ b/src/Symfony/Component/RateLimiter/Exception/MaxWaitDurationExceededException.php @@ -11,7 +11,7 @@ namespace Symfony\Component\RateLimiter\Exception; -use Symfony\Component\RateLimiter\Limit; +use Symfony\Component\RateLimiter\RateLimit; /** * @author Wouter de Jong @@ -20,17 +20,17 @@ */ class MaxWaitDurationExceededException extends \RuntimeException { - private $limit; + private $rateLimit; - public function __construct(string $message, Limit $limit, int $code = 0, ?\Throwable $previous = null) + public function __construct(string $message, RateLimit $rateLimit, int $code = 0, ?\Throwable $previous = null) { parent::__construct($message, $code, $previous); - $this->limit = $limit; + $this->rateLimit = $rateLimit; } - public function getLimit(): Limit + public function getRateLimit(): RateLimit { - return $this->limit; + return $this->rateLimit; } } diff --git a/src/Symfony/Component/RateLimiter/Exception/RateLimitExceededException.php b/src/Symfony/Component/RateLimiter/Exception/RateLimitExceededException.php index f96516e653bb0..0cb10c750befe 100644 --- a/src/Symfony/Component/RateLimiter/Exception/RateLimitExceededException.php +++ b/src/Symfony/Component/RateLimiter/Exception/RateLimitExceededException.php @@ -11,7 +11,7 @@ namespace Symfony\Component\RateLimiter\Exception; -use Symfony\Component\RateLimiter\Limit; +use Symfony\Component\RateLimiter\RateLimit; /** * @author Kevin Bond @@ -20,27 +20,32 @@ */ class RateLimitExceededException extends \RuntimeException { - private $limit; + private $rateLimit; - public function __construct(Limit $limit, $code = 0, \Throwable $previous = null) + public function __construct(RateLimit $rateLimit, $code = 0, \Throwable $previous = null) { parent::__construct('Rate Limit Exceeded', $code, $previous); - $this->limit = $limit; + $this->rateLimit = $rateLimit; } - public function getLimit(): Limit + public function getRateLimit(): RateLimit { - return $this->limit; + return $this->rateLimit; } public function getRetryAfter(): \DateTimeImmutable { - return $this->limit->getRetryAfter(); + return $this->rateLimit->getRetryAfter(); } public function getRemainingTokens(): int { - return $this->limit->getRemainingTokens(); + return $this->rateLimit->getRemainingTokens(); + } + + public function getLimit(): int + { + return $this->rateLimit->getLimit(); } } diff --git a/src/Symfony/Component/RateLimiter/FixedWindowLimiter.php b/src/Symfony/Component/RateLimiter/FixedWindowLimiter.php index 9164eb4ae55ee..bb0135d76980b 100644 --- a/src/Symfony/Component/RateLimiter/FixedWindowLimiter.php +++ b/src/Symfony/Component/RateLimiter/FixedWindowLimiter.php @@ -64,19 +64,19 @@ public function reserve(int $tokens = 1, ?float $maxTime = null): Reservation if ($availableTokens >= $tokens) { $window->add($tokens); - $reservation = new Reservation($now, new Limit($window->getAvailableTokens($now), \DateTimeImmutable::createFromFormat('U', floor($now)), true)); + $reservation = new Reservation($now, new RateLimit($window->getAvailableTokens($now), \DateTimeImmutable::createFromFormat('U', floor($now)), true, $this->limit)); } else { $remainingTokens = $tokens - $availableTokens; $waitDuration = $window->calculateTimeForTokens($remainingTokens); if (null !== $maxTime && $waitDuration > $maxTime) { // process needs to wait longer than set interval - throw new MaxWaitDurationExceededException(sprintf('The rate limiter wait time ("%d" seconds) is longer than the provided maximum time ("%d" seconds).', $waitDuration, $maxTime), new Limit($window->getAvailableTokens($now), \DateTimeImmutable::createFromFormat('U', floor($now + $waitDuration)), false)); + 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)); } $window->add($tokens); - $reservation = new Reservation($now + $waitDuration, new Limit($window->getAvailableTokens($now), \DateTimeImmutable::createFromFormat('U', floor($now + $waitDuration)), false)); + $reservation = new Reservation($now + $waitDuration, new RateLimit($window->getAvailableTokens($now), \DateTimeImmutable::createFromFormat('U', floor($now + $waitDuration)), false, $this->limit)); } $this->storage->save($window); } finally { @@ -89,12 +89,12 @@ public function reserve(int $tokens = 1, ?float $maxTime = null): Reservation /** * {@inheritdoc} */ - public function consume(int $tokens = 1): Limit + public function consume(int $tokens = 1): RateLimit { try { - return $this->reserve($tokens, 0)->getLimit(); + return $this->reserve($tokens, 0)->getRateLimit(); } catch (MaxWaitDurationExceededException $e) { - return $e->getLimit(); + return $e->getRateLimit(); } } diff --git a/src/Symfony/Component/RateLimiter/LimiterInterface.php b/src/Symfony/Component/RateLimiter/LimiterInterface.php index e04a7ea26b4f0..f190f56354e64 100644 --- a/src/Symfony/Component/RateLimiter/LimiterInterface.php +++ b/src/Symfony/Component/RateLimiter/LimiterInterface.php @@ -43,7 +43,7 @@ public function reserve(int $tokens = 1, ?float $maxTime = null): Reservation; * * @param int $tokens the number of tokens required */ - public function consume(int $tokens = 1): Limit; + public function consume(int $tokens = 1): RateLimit; /** * Resets the limit. diff --git a/src/Symfony/Component/RateLimiter/NoLimiter.php b/src/Symfony/Component/RateLimiter/NoLimiter.php index 65f772a66efe1..13ccbf10b6c0e 100644 --- a/src/Symfony/Component/RateLimiter/NoLimiter.php +++ b/src/Symfony/Component/RateLimiter/NoLimiter.php @@ -25,12 +25,12 @@ final class NoLimiter implements LimiterInterface { public function reserve(int $tokens = 1, ?float $maxTime = null): Reservation { - return new Reservation(time(), new Limit(\INF, new \DateTimeImmutable(), true)); + return new Reservation(time(), new RateLimit(\INF, new \DateTimeImmutable(), true, \INF)); } - public function consume(int $tokens = 1): Limit + public function consume(int $tokens = 1): RateLimit { - return new Limit(\INF, new \DateTimeImmutable(), true); + return new RateLimit(\INF, new \DateTimeImmutable(), true, \INF); } public function reset(): void diff --git a/src/Symfony/Component/RateLimiter/Limit.php b/src/Symfony/Component/RateLimiter/RateLimit.php similarity index 87% rename from src/Symfony/Component/RateLimiter/Limit.php rename to src/Symfony/Component/RateLimiter/RateLimit.php index fb59ceb127cd4..64c706b6e6562 100644 --- a/src/Symfony/Component/RateLimiter/Limit.php +++ b/src/Symfony/Component/RateLimiter/RateLimit.php @@ -18,17 +18,19 @@ * * @experimental in 5.2 */ -class Limit +class RateLimit { private $availableTokens; private $retryAfter; private $accepted; + private $limit; - public function __construct(int $availableTokens, \DateTimeImmutable $retryAfter, bool $accepted) + public function __construct(int $availableTokens, \DateTimeImmutable $retryAfter, bool $accepted, int $limit) { $this->availableTokens = $availableTokens; $this->retryAfter = $retryAfter; $this->accepted = $accepted; + $this->limit = $limit; } public function isAccepted(): bool @@ -58,6 +60,11 @@ public function getRemainingTokens(): int return $this->availableTokens; } + public function getLimit(): int + { + return $this->limit; + } + public function wait(): void { sleep(($this->retryAfter->getTimestamp() - time()) * 1e6); diff --git a/src/Symfony/Component/RateLimiter/Reservation.php b/src/Symfony/Component/RateLimiter/Reservation.php index 26a1d1750d44d..4ea54ce5a8816 100644 --- a/src/Symfony/Component/RateLimiter/Reservation.php +++ b/src/Symfony/Component/RateLimiter/Reservation.php @@ -19,15 +19,15 @@ final class Reservation { private $timeToAct; - private $limit; + private $rateLimit; /** * @param float $timeToAct Unix timestamp in seconds when this reservation should act */ - public function __construct(float $timeToAct, Limit $limit) + public function __construct(float $timeToAct, RateLimit $rateLimit) { $this->timeToAct = $timeToAct; - $this->limit = $limit; + $this->rateLimit = $rateLimit; } public function getTimeToAct(): float @@ -40,9 +40,9 @@ public function getWaitDuration(): float return max(0, (-microtime(true)) + $this->timeToAct); } - public function getLimit(): Limit + public function getRateLimit(): RateLimit { - return $this->limit; + return $this->rateLimit; } public function wait(): void diff --git a/src/Symfony/Component/RateLimiter/SlidingWindowLimiter.php b/src/Symfony/Component/RateLimiter/SlidingWindowLimiter.php index dcdf6198439d2..4d89e89615fcb 100644 --- a/src/Symfony/Component/RateLimiter/SlidingWindowLimiter.php +++ b/src/Symfony/Component/RateLimiter/SlidingWindowLimiter.php @@ -76,7 +76,7 @@ public function reserve(int $tokens = 1, ?float $maxTime = null): Reservation /** * {@inheritdoc} */ - public function consume(int $tokens = 1): Limit + public function consume(int $tokens = 1): RateLimit { $this->lock->acquire(true); @@ -91,13 +91,13 @@ public function consume(int $tokens = 1): Limit $hitCount = $window->getHitCount(); $availableTokens = $this->getAvailableTokens($hitCount); if ($availableTokens < $tokens) { - return new Limit($availableTokens, $window->getRetryAfter(), false); + return new RateLimit($availableTokens, $window->getRetryAfter(), false, $this->limit); } $window->add($tokens); $this->storage->save($window); - return new Limit($this->getAvailableTokens($window->getHitCount()), $window->getRetryAfter(), true); + return new RateLimit($this->getAvailableTokens($window->getHitCount()), $window->getRetryAfter(), true, $this->limit); } finally { $this->lock->release(); } diff --git a/src/Symfony/Component/RateLimiter/Tests/FixedWindowLimiterTest.php b/src/Symfony/Component/RateLimiter/Tests/FixedWindowLimiterTest.php index a6f436616f933..8ae6dcc875c24 100644 --- a/src/Symfony/Component/RateLimiter/Tests/FixedWindowLimiterTest.php +++ b/src/Symfony/Component/RateLimiter/Tests/FixedWindowLimiterTest.php @@ -41,10 +41,12 @@ public function testConsume() sleep(5); } - $limit = $limiter->consume(); - $this->assertTrue($limit->isAccepted()); - $limit = $limiter->consume(); - $this->assertFalse($limit->isAccepted()); + $rateLimit = $limiter->consume(); + $this->assertSame(10, $rateLimit->getLimit()); + $this->assertTrue($rateLimit->isAccepted()); + $rateLimit = $limiter->consume(); + $this->assertFalse($rateLimit->isAccepted()); + $this->assertSame(10, $rateLimit->getLimit()); } public function testConsumeOutsideInterval() @@ -58,18 +60,18 @@ public function testConsumeOutsideInterval() $limiter->consume(9); // ...try bursting again at the start of the next window sleep(10); - $limit = $limiter->consume(10); - $this->assertEquals(0, $limit->getRemainingTokens()); - $this->assertTrue($limit->isAccepted()); + $rateLimit = $limiter->consume(10); + $this->assertEquals(0, $rateLimit->getRemainingTokens()); + $this->assertTrue($rateLimit->isAccepted()); } public function testWrongWindowFromCache() { $this->storage->save(new DummyWindow()); $limiter = $this->createLimiter(); - $limit = $limiter->consume(); - $this->assertTrue($limit->isAccepted()); - $this->assertEquals(9, $limit->getRemainingTokens()); + $rateLimit = $limiter->consume(); + $this->assertTrue($rateLimit->isAccepted()); + $this->assertEquals(9, $rateLimit->getRemainingTokens()); } private function createLimiter(): FixedWindowLimiter diff --git a/src/Symfony/Component/RateLimiter/Tests/LimitTest.php b/src/Symfony/Component/RateLimiter/Tests/RateLimitTest.php similarity index 67% rename from src/Symfony/Component/RateLimiter/Tests/LimitTest.php rename to src/Symfony/Component/RateLimiter/Tests/RateLimitTest.php index a9865811146b6..c62eda36f4fd2 100644 --- a/src/Symfony/Component/RateLimiter/Tests/LimitTest.php +++ b/src/Symfony/Component/RateLimiter/Tests/RateLimitTest.php @@ -13,25 +13,25 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\RateLimiter\Exception\RateLimitExceededException; -use Symfony\Component\RateLimiter\Limit; +use Symfony\Component\RateLimiter\RateLimit; -class LimitTest extends TestCase +class RateLimitTest extends TestCase { public function testEnsureAcceptedDoesNotThrowExceptionIfAccepted() { - $limit = new Limit(10, new \DateTimeImmutable(), true); + $rateLimit = new RateLimit(10, new \DateTimeImmutable(), true, 10); - $this->assertSame($limit, $limit->ensureAccepted()); + $this->assertSame($rateLimit, $rateLimit->ensureAccepted()); } public function testEnsureAcceptedThrowsRateLimitExceptionIfNotAccepted() { - $limit = new Limit(10, $retryAfter = new \DateTimeImmutable(), false); + $rateLimit = new RateLimit(10, $retryAfter = new \DateTimeImmutable(), false, 10); try { - $limit->ensureAccepted(); + $rateLimit->ensureAccepted(); } catch (RateLimitExceededException $exception) { - $this->assertSame($limit, $exception->getLimit()); + $this->assertSame($rateLimit, $exception->getRateLimit()); $this->assertSame(10, $exception->getRemainingTokens()); $this->assertSame($retryAfter, $exception->getRetryAfter()); diff --git a/src/Symfony/Component/RateLimiter/Tests/SlidingWindowLimiterTest.php b/src/Symfony/Component/RateLimiter/Tests/SlidingWindowLimiterTest.php index 341f216c29df4..07146c765d6d0 100644 --- a/src/Symfony/Component/RateLimiter/Tests/SlidingWindowLimiterTest.php +++ b/src/Symfony/Component/RateLimiter/Tests/SlidingWindowLimiterTest.php @@ -38,17 +38,19 @@ public function testConsume() $limiter->consume(8); sleep(15); - $limit = $limiter->consume(); - $this->assertTrue($limit->isAccepted()); + $rateLimit = $limiter->consume(); + $this->assertTrue($rateLimit->isAccepted()); + $this->assertSame(10, $rateLimit->getLimit()); // We are 25% into the new window - $limit = $limiter->consume(5); - $this->assertFalse($limit->isAccepted()); - $this->assertEquals(3, $limit->getRemainingTokens()); + $rateLimit = $limiter->consume(5); + $this->assertFalse($rateLimit->isAccepted()); + $this->assertEquals(3, $rateLimit->getRemainingTokens()); sleep(13); - $limit = $limiter->consume(10); - $this->assertTrue($limit->isAccepted()); + $rateLimit = $limiter->consume(10); + $this->assertTrue($rateLimit->isAccepted()); + $this->assertSame(10, $rateLimit->getLimit()); } public function testReserve() diff --git a/src/Symfony/Component/RateLimiter/Tests/TokenBucketLimiterTest.php b/src/Symfony/Component/RateLimiter/Tests/TokenBucketLimiterTest.php index 714ff15063087..b5b83649e20d9 100644 --- a/src/Symfony/Component/RateLimiter/Tests/TokenBucketLimiterTest.php +++ b/src/Symfony/Component/RateLimiter/Tests/TokenBucketLimiterTest.php @@ -74,26 +74,28 @@ public function testConsume() $limiter = $this->createLimiter(10, $rate); // enough free tokens - $limit = $limiter->consume(5); - $this->assertTrue($limit->isAccepted()); - $this->assertEquals(5, $limit->getRemainingTokens()); - $this->assertEqualsWithDelta(time(), $limit->getRetryAfter()->getTimestamp(), 1); + $rateLimit = $limiter->consume(5); + $this->assertTrue($rateLimit->isAccepted()); + $this->assertEquals(5, $rateLimit->getRemainingTokens()); + $this->assertEqualsWithDelta(time(), $rateLimit->getRetryAfter()->getTimestamp(), 1); + $this->assertSame(10, $rateLimit->getLimit()); // there are only 5 available free tokens left now - $limit = $limiter->consume(10); - $this->assertEquals(5, $limit->getRemainingTokens()); + $rateLimit = $limiter->consume(10); + $this->assertEquals(5, $rateLimit->getRemainingTokens()); - $limit = $limiter->consume(5); - $this->assertEquals(0, $limit->getRemainingTokens()); - $this->assertEqualsWithDelta(time(), $limit->getRetryAfter()->getTimestamp(), 1); + $rateLimit = $limiter->consume(5); + $this->assertEquals(0, $rateLimit->getRemainingTokens()); + $this->assertEqualsWithDelta(time(), $rateLimit->getRetryAfter()->getTimestamp(), 1); + $this->assertSame(10, $rateLimit->getLimit()); } public function testWrongWindowFromCache() { $this->storage->save(new DummyWindow()); $limiter = $this->createLimiter(); - $limit = $limiter->consume(); - $this->assertTrue($limit->isAccepted()); - $this->assertEquals(9, $limit->getRemainingTokens()); + $rateLimit = $limiter->consume(); + $this->assertTrue($rateLimit->isAccepted()); + $this->assertEquals(9, $rateLimit->getRemainingTokens()); } private function createLimiter($initialTokens = 10, Rate $rate = null) diff --git a/src/Symfony/Component/RateLimiter/TokenBucketLimiter.php b/src/Symfony/Component/RateLimiter/TokenBucketLimiter.php index b8997ac7e04a8..64b3046ec336d 100644 --- a/src/Symfony/Component/RateLimiter/TokenBucketLimiter.php +++ b/src/Symfony/Component/RateLimiter/TokenBucketLimiter.php @@ -74,16 +74,16 @@ public function reserve(int $tokens = 1, ?float $maxTime = null): Reservation $bucket->setTokens($availableTokens - $tokens); $bucket->setTimer($now); - $reservation = new Reservation($now, new Limit($bucket->getAvailableTokens($now), \DateTimeImmutable::createFromFormat('U', floor($now)), true)); + $reservation = new Reservation($now, new RateLimit($bucket->getAvailableTokens($now), \DateTimeImmutable::createFromFormat('U', floor($now)), true, $this->maxBurst)); } else { $remainingTokens = $tokens - $availableTokens; $waitDuration = $this->rate->calculateTimeForTokens($remainingTokens); if (null !== $maxTime && $waitDuration > $maxTime) { // process needs to wait longer than set interval - $limit = new Limit($availableTokens, \DateTimeImmutable::createFromFormat('U', floor($now + $waitDuration)), false); + $rateLimit = new RateLimit($availableTokens, \DateTimeImmutable::createFromFormat('U', floor($now + $waitDuration)), false, $this->maxBurst); - throw new MaxWaitDurationExceededException(sprintf('The rate limiter wait time ("%d" seconds) is longer than the provided maximum time ("%d" seconds).', $waitDuration, $maxTime), $limit); + throw new MaxWaitDurationExceededException(sprintf('The rate limiter wait time ("%d" seconds) is longer than the provided maximum time ("%d" seconds).', $waitDuration, $maxTime), $rateLimit); } // at $now + $waitDuration all tokens will be reserved for this process, @@ -91,7 +91,7 @@ public function reserve(int $tokens = 1, ?float $maxTime = null): Reservation $bucket->setTokens(0); $bucket->setTimer($now + $waitDuration); - $reservation = new Reservation($bucket->getTimer(), new Limit(0, \DateTimeImmutable::createFromFormat('U', floor($now + $waitDuration)), false)); + $reservation = new Reservation($bucket->getTimer(), new RateLimit(0, \DateTimeImmutable::createFromFormat('U', floor($now + $waitDuration)), false, $this->maxBurst)); } $this->storage->save($bucket); @@ -105,12 +105,12 @@ public function reserve(int $tokens = 1, ?float $maxTime = null): Reservation /** * {@inheritdoc} */ - public function consume(int $tokens = 1): Limit + public function consume(int $tokens = 1): RateLimit { try { - return $this->reserve($tokens, 0)->getLimit(); + return $this->reserve($tokens, 0)->getRateLimit(); } catch (MaxWaitDurationExceededException $e) { - return $e->getLimit(); + return $e->getRateLimit(); } } }