public function reserve(int
$tokens = 1, float
$maxTime = null
): Reservation
{ if ($tokens >
$this->limit
) { throw new \
InvalidArgumentException(sprintf('Cannot reserve more tokens (%d) than the size of the rate limiter (%d).',
$tokens,
$this->limit
));
} $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);