$this->lock?->
acquire(true
);
try { $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($now,
new 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
));
}