Skip to content

Allow retrieval of current RateLimit without actually consuming #60551

Open
@heiglandreas

Description

@heiglandreas

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));
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions