public function reserve(int
$tokens = 1, float
$maxTime = null
): Reservation
{ if ($tokens >
$this->maxBurst
) { throw new \
InvalidArgumentException(sprintf('Cannot reserve more tokens (%d) than the burst size of the rate limiter (%d).',
$tokens,
$this->maxBurst
));
} $this->lock?->
acquire(true
);
try { $bucket =
$this->storage->
fetch($this->id
);
if (!
$bucket instanceof TokenBucket
) { $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($now,
new RateLimit($bucket->
getAvailableTokens($now), \DateTimeImmutable::
createFromFormat('U',
floor($now)), true,
$this->maxBurst
));
}