[RateLimiter] rename Limit to RateLimit and add RateLimit::getLimit()
This commit is contained in:
parent
1d445cce63
commit
c5361cfc58
@ -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 @@ use Symfony\Component\RateLimiter\NoLimiter;
|
||||
*/
|
||||
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
|
||||
|
@ -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 @@ use Symfony\Component\RateLimiter\Limit;
|
||||
*/
|
||||
interface RequestRateLimiterInterface
|
||||
{
|
||||
public function consume(Request $request): Limit;
|
||||
public function consume(Request $request): RateLimit;
|
||||
|
||||
public function reset(Request $request): void;
|
||||
}
|
||||
|
@ -38,18 +38,18 @@ final class CompoundLimiter implements LimiterInterface
|
||||
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
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\RateLimiter\Exception;
|
||||
|
||||
use Symfony\Component\RateLimiter\Limit;
|
||||
use Symfony\Component\RateLimiter\RateLimit;
|
||||
|
||||
/**
|
||||
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||
@ -20,17 +20,17 @@ use Symfony\Component\RateLimiter\Limit;
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\RateLimiter\Exception;
|
||||
|
||||
use Symfony\Component\RateLimiter\Limit;
|
||||
use Symfony\Component\RateLimiter\RateLimit;
|
||||
|
||||
/**
|
||||
* @author Kevin Bond <kevinbond@gmail.com>
|
||||
@ -20,27 +20,32 @@ use Symfony\Component\RateLimiter\Limit;
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -64,19 +64,19 @@ final class FixedWindowLimiter implements LimiterInterface
|
||||
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 @@ final class FixedWindowLimiter implements LimiterInterface
|
||||
/**
|
||||
* {@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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ interface LimiterInterface
|
||||
*
|
||||
* @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.
|
||||
|
@ -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
|
||||
|
@ -18,17 +18,19 @@ use Symfony\Component\RateLimiter\Exception\RateLimitExceededException;
|
||||
*
|
||||
* @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 @@ class Limit
|
||||
return $this->availableTokens;
|
||||
}
|
||||
|
||||
public function getLimit(): int
|
||||
{
|
||||
return $this->limit;
|
||||
}
|
||||
|
||||
public function wait(): void
|
||||
{
|
||||
sleep(($this->retryAfter->getTimestamp() - time()) * 1e6);
|
@ -19,15 +19,15 @@ namespace Symfony\Component\RateLimiter;
|
||||
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 @@ final class Reservation
|
||||
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
|
||||
|
@ -76,7 +76,7 @@ final class SlidingWindowLimiter implements LimiterInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function consume(int $tokens = 1): Limit
|
||||
public function consume(int $tokens = 1): RateLimit
|
||||
{
|
||||
$this->lock->acquire(true);
|
||||
|
||||
@ -91,13 +91,13 @@ final class SlidingWindowLimiter implements LimiterInterface
|
||||
$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();
|
||||
}
|
||||
|
@ -41,10 +41,12 @@ class FixedWindowLimiterTest extends TestCase
|
||||
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 @@ class FixedWindowLimiterTest extends TestCase
|
||||
$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
|
||||
|
@ -13,25 +13,25 @@ namespace Symfony\Component\RateLimiter\Tests;
|
||||
|
||||
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());
|
||||
|
@ -38,17 +38,19 @@ class SlidingWindowLimiterTest extends TestCase
|
||||
$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()
|
||||
|
@ -74,26 +74,28 @@ class TokenBucketLimiterTest extends TestCase
|
||||
$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)
|
||||
|
@ -74,16 +74,16 @@ final class TokenBucketLimiter implements LimiterInterface
|
||||
$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 @@ final class TokenBucketLimiter implements LimiterInterface
|
||||
$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 @@ final class TokenBucketLimiter implements LimiterInterface
|
||||
/**
|
||||
* {@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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user