Description
Description
Right now the only way to get a RateLimit
instance is to actually consume a token. I have so far not seen a way to get the RateLimit
without that. Trying to retrieve the RateLimit
without consuming a token by using 0
as parameter to RateLimiterInterface::consume()
didn't work out the way I expected as - at least in the SLidingWindowLimiter
the RateLimit::isAccepted()
will always return true - even when there is no token available any more.
This behaviour makes sense as I am not consuming a token.
Having a way to get a RateLimit
that has the isAccepted
method return true
or false
depending on the currently available tokens would be helpful for applications that consume a token under certain circumstances along the code-path but that want to immediately at the beginning stop processing when no token is available any more. That way the application can save a lot of processing time before coming to the conclusion that the limit has been reached.
Example
public function myAction(): Request
{
// This is what we currently try which does not work
//$limit = $this->rateLimiter->consume(0)
$limit = $this->rateLimiter->getCurrentLimit();
if (! $limit->isAccepted()) {
throw new TooManyRequestsHttpException($limit->getRetryAfter()->getTimestamp());
}
// ... do some heavy computing stuff here
if (/* add some condition here */ true) {
// We only want to consume a token under certain circumstances
$this->rateLimiter->consume(1);
}
}
Example implementation for the sliding window ratelimiter:
public function getCurrentLimit(): RateLimit
{
$now = microtime(true);
$hitCount = $window->getHitCount();
$availableTokens = $this->getAvailableTokens($hitCount);
$resetDuration = $window->calculateTimeForTokens($this->limit, $window->getHitCount());
$resetTime = \DateTimeImmutable::createFromFormat('U', $availableTokens ? floor($now) : floor($now + $resetDuration));
return new RateLimit($availableTokens, $resetTime, $availableTokens > 0, $this->limit));
}