Not sure if the getEstimate() gives out correct waiting time
NinoSkopac opened this issue · comments
I've done a couple of tests:
- If I limit the requests to 1 per minute: I do the request, and then I cannot do it for the next 60 seconds. Good.
- If I limit the requests to 2 per minute: I do the requests, and then I have to wait 30 seconds. Is this how it should be?
Let's look at it from a end-user POV, not programming: if I make 2 requests one after another, and the rate limit is 2 per 60 seconds, should I wait 30 seconds or 60 seconds in order to do a 3rd one? I'd say 60.
Code excerpts from my internal user class:
public const Rate_Limits = [ // [$limit, $time] where $time is in seconds
[2, 1],
[2, 60], // testing value of 2 for dev purposes, will be something like 10 in production
[150, 3600]
];
// from constructor; classes are aliased
self::$LeakyBucket = new LeakyBucket;
self::$LeakyBucket->setStorage(new StiphleApcu);
/**
* If the returned value is null, it means there's no throttling needed for this request.
*
* @return array|null
*/
public static function getRateLimitRemaining(): ?array
{
$uid = self::getInternalUserIdentifier();
foreach (self::Rate_Limits as [$limit, $seconds]) {
$estimate = self::$LeakyBucket->getEstimate($uid, $limit, $seconds * 1000);
if ($estimate === 0)
self::$LeakyBucket->throttle($uid, $limit, $seconds * 1000);
else
return [
'request_limit' => $limit,
'estimated_wait_miliseconds' => $estimate,
'estimated_wait_human_readable' => Parse::secondsToHoursMinutesSeconds((int) round($estimate / 1000)),
'timeframe_seconds' => $seconds,
'timeframe_seconds_human_readable' => Parse::secondsToHoursMinutesSeconds($seconds),
];
}
return null;
}
php 7.1.1, ubuntu 16
The Leaky Bucket algorithm is a little like a rolling minute. It only throttles when the bucket is full. So, initially, you can burst to fill the bucket, but after that, it's more like the timings you would expect.
If you want something that might be a little easier for your users to understand, you can use the TimeWindow
throttle, which works based on you can do 2 requests between 00:00:00 and 00:00:01, 2 requests between 00:00:01 and 00:00:02 etc.