$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($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
$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);
} // at $now + $waitDuration all tokens will be reserved for this process,
// so no tokens are left for other processes.
$bucket->
setTokens($availableTokens -
$tokens);