Fix rate limit (#1015)

* Rate limit fix

If $elapsed_seconds > $this->intervalSeconds the first time hasRequestQuota() is called, rateLimitReached is never set to true and the limit is not enforced
This can happen if the rate limit is set in a callback function some time after starting

I completely removed $rateLimitReached since its only use was in the removed condition check

Alternatively, it should be possible to reinitialize currentStartTime when setRateLimit is called, but I still don't really see the usefulness of resetting the timer only when the limit was reached in the previous interval

* Rename variable

* Clean up

---------

Co-authored-by: Riccardo Nava <116394015+ricnava00@users.noreply.github.com>
This commit is contained in:
Zach Borboa
2025-11-15 17:08:55 -05:00
committed by GitHub
parent 14e0881af7
commit 4bf7292438
2 changed files with 13 additions and 14 deletions
+12 -13
View File
@@ -24,7 +24,7 @@ class MultiCurl extends BaseCurl
private $rateLimit = null;
private $rateLimitEnabled = false;
private $rateLimitReached = false;
private $maxRequests = null;
private $maxRequestsPerInterval = null;
private $interval = null;
private $intervalSeconds = null;
private $unit = null;
@@ -579,12 +579,12 @@ class MultiCurl extends BaseCurl
'';
if (!preg_match($rate_limit_pattern, $rate_limit, $matches)) {
throw new \UnexpectedValueException(
'rate limit must be formatted as $max_requests/$interval(s|m|h) ' .
'rate limit must be formatted as $max_requests_per_interval/$interval(s|m|h) ' .
'(e.g. "60/1m" for a maximum of 60 requests per 1 minute)'
);
}
$max_requests = (int)$matches['1'];
$max_requests_per_interval = (int)$matches['1'];
if ($matches['2'] === '') {
$interval = 1;
} else {
@@ -602,9 +602,9 @@ class MultiCurl extends BaseCurl
$interval_seconds = $interval * 3600;
}
$this->rateLimit = (string)$max_requests . '/' . (string)$interval . $unit;
$this->rateLimit = (string)$max_requests_per_interval . '/' . (string)$interval . $unit;
$this->rateLimitEnabled = true;
$this->maxRequests = $max_requests;
$this->maxRequestsPerInterval = $max_requests_per_interval;
$this->interval = $interval;
$this->intervalSeconds = $interval_seconds;
$this->unit = $unit;
@@ -919,23 +919,22 @@ class MultiCurl extends BaseCurl
// Calculate if there's request quota since ratelimiting is enabled.
if ($this->rateLimitEnabled) {
// Determine if the limit of requests per interval has been reached.
if ($this->currentRequestCount >= $this->maxRequests) {
if ($this->currentRequestCount >= $this->maxRequestsPerInterval) {
$micro_time = microtime(true);
$elapsed_seconds = $micro_time - $this->currentStartTime;
if ($elapsed_seconds <= $this->intervalSeconds) {
$this->rateLimitReached = true;
// Rate limit reached.
return false;
} elseif ($this->rateLimitReached) {
$this->rateLimitReached = false;
} else {
// Rate limit not reached. Rate limit interval has passed,
// reset counters.
$this->currentStartTime = $micro_time;
$this->currentRequestCount = 0;
}
}
return true;
} else {
return true;
}
return true;
}
/**
+1 -1
View File
@@ -5020,7 +5020,7 @@ class PHPMultiCurlClassTest extends \PHPUnit\Framework\TestCase
);
$this->assertEquals(
$test['expected']['max_requests'],
\Helper\get_multi_curl_property_value($multi_curl, 'maxRequests')
\Helper\get_multi_curl_property_value($multi_curl, 'maxRequestsPerInterval')
);
$this->assertEquals(
$test['expected']['interval'],