RateLimit example

try {
            $window = $this->storage->fetch($this->id);
            if (!$window instanceof SlidingWindow) {
                $window = new SlidingWindow($this->id, $this->interval);
            } elseif ($window->isExpired()) {
                $window = SlidingWindow::createFromPreviousWindow($window$this->interval);
            }

            $hitCount = $window->getHitCount();
            $availableTokens = $this->getAvailableTokens($hitCount);
            if ($availableTokens < $tokens) {
                return new RateLimit($availableTokens$window->getRetryAfter(), false, $this->limit);
            }

            $window->add($tokens);

            if (0 < $tokens) {
                $this->storage->save($window);
            }

            return new RateLimit($this->getAvailableTokens($window->getHitCount())$window->getRetryAfter(), true, $this->limit);
        } finally {
            $this->lock?->release();
        }
use Symfony\Bridge\PhpUnit\ClockMock;
use Symfony\Component\RateLimiter\Exception\RateLimitExceededException;
use Symfony\Component\RateLimiter\RateLimit;

/** * @group time-sensitive */
class RateLimitTest extends TestCase
{
    public function testEnsureAcceptedDoesNotThrowExceptionIfAccepted()
    {
        $rateLimit = new RateLimit(10, new \DateTimeImmutable(), true, 10);

        $this->assertSame($rateLimit$rateLimit->ensureAccepted());
    }

    public function testEnsureAcceptedThrowsRateLimitExceptionIfNotAccepted()
    {
        $rateLimit = new RateLimit(10, $retryAfter = new \DateTimeImmutable(), false, 10);

        try {
            $rateLimit->ensureAccepted();
        } catch (RateLimitExceededException $exception) {
            
 $rateLimits));

        $this->assertSame($expected$rateLimiter->consume(new Request()));
    }

    public static function provideRateLimits()
    {
        $now = new \DateTimeImmutable();

        yield 'Both accepted with different count of remaining tokens' => [
            [
                $expected = new RateLimit(0, $now, true, 1), // less remaining tokens                 new RateLimit(1, $now, true, 1),
            ],
            $expected,
        ];

        yield 'Both accepted with same count of remaining tokens' => [
            [
                $expected = new RateLimit(0, $now->add(new \DateInterval('P1D')), true, 1), // longest wait time                 new RateLimit(0, $now, true, 1),
            ],
            $expected,
        ];

final class NoLimiter implements LimiterInterface
{
    public function reserve(int $tokens = 1, float $maxTime = null): Reservation
    {
        return new Reservation(microtime(true)new RateLimit(\PHP_INT_MAX, new \DateTimeImmutable(), true, \PHP_INT_MAX));
    }

    public function consume(int $tokens = 1): RateLimit
    {
        return new RateLimit(\PHP_INT_MAX, new \DateTimeImmutable(), true, \PHP_INT_MAX);
    }

    public function reset(): void
    {
    }
}
$bucket = new TokenBucket($this->id, $this->maxBurst, $this->rate);
            }

            $now = microtime(true);
            $availableTokens = $bucket->getAvailableTokens($now);

            if ($availableTokens >= max(1, $tokens)) {
                // tokens are now available, update bucket                 $bucket->setTokens($availableTokens - $tokens);
                $bucket->setTimer($now);

                $reservation = new Reservation($nownew 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                     $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)$rateLimit);
                }

                
$window = $this->storage->fetch($this->id);
            if (!$window instanceof Window) {
                $window = new Window($this->id, $this->interval, $this->limit);
            }

            $now = microtime(true);
            $availableTokens = $window->getAvailableTokens($now);

            if ($availableTokens >= max(1, $tokens)) {
                $window->add($tokens$now);

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

                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 RateLimit($window->getAvailableTokens($now), \DateTimeImmutable::createFromFormat('U', floor($now + $waitDuration)), false, $this->limit));
                }

                $window->add($tokens$now);

                $reservation = new Reservation($now + $waitDurationnew RateLimit($window->getAvailableTokens($now), \DateTimeImmutable::createFromFormat('U', floor($now + $waitDuration)), false, $this->limit));
            }
Home | Imprint | This part of the site doesn't use cookies.