Actualiser api/index.php
CI / PHP Syntax Check (push) Has been cancelled
CI / JavaScript Lint (push) Has been cancelled
CI / Docker Build Test (push) Has been cancelled
CI / Validate Translation Files (push) Has been cancelled
CI / Auto-merge develop → main (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
Security Scan (Trivy) / Trivy — Docker image scan (push) Has been cancelled
Security Scan (Trivy) / Trivy — Filesystem scan (push) Has been cancelled
CI / PHP Syntax Check (push) Has been cancelled
CI / JavaScript Lint (push) Has been cancelled
CI / Docker Build Test (push) Has been cancelled
CI / Validate Translation Files (push) Has been cancelled
CI / Auto-merge develop → main (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
Security Scan (Trivy) / Trivy — Docker image scan (push) Has been cancelled
Security Scan (Trivy) / Trivy — Filesystem scan (push) Has been cancelled
This commit is contained in:
+16
-3
@@ -5414,6 +5414,7 @@ function saveSettings(): void {
|
||||
*/
|
||||
function callGemini(string $url, array $payload, int $timeout = 60): array {
|
||||
$maxAttempts = 4;
|
||||
$maxTotalElapsed = 45; // budget de sécurité pour ne jamais approcher le set_time_limit(120) de PHP
|
||||
$lastCode = 0;
|
||||
$lastBody = '';
|
||||
$promptLen = strlen(json_encode($payload));
|
||||
@@ -5445,24 +5446,36 @@ function callGemini(string $url, array $payload, int $timeout = 60): array {
|
||||
|
||||
if ($body !== false) $lastBody = $body;
|
||||
|
||||
// Success or non-retryable error → stop immediately
|
||||
// Success or non-retryable error → stop immediately
|
||||
if ($lastCode === 200) break;
|
||||
if ($lastCode !== 429 && $lastCode !== 503) break;
|
||||
if ($attempt >= $maxAttempts) break;
|
||||
|
||||
// Quota épuisé (RESOURCE_EXHAUSTED) n'est PAS transitoire — retenter le même modèle
|
||||
// dans cette requête ne servira à rien. On échoue vite plutôt que de risquer que PHP
|
||||
// tue le script en plein milieu (ce qui remonte comme un 502/504 moche côté client).
|
||||
$errData = $body ? json_decode($body, true) : null;
|
||||
if (($errData['error']['status'] ?? '') === 'RESOURCE_EXHAUSTED') {
|
||||
EverLog::warn('AI quota exhausted, failing fast', ['code' => $lastCode]);
|
||||
break;
|
||||
}
|
||||
|
||||
// Determine how long to wait -----------------------------------------------
|
||||
// Priority 1: Retry-After header (set by Google in some 429 responses)
|
||||
$waitSec = $retryAfterHeader ?? ($attempt * 2); // default: 2 s, 4 s, 6 s
|
||||
|
||||
// Priority 2: Google's retryDelay inside the error body (e.g. {"retryDelay":"10s"})
|
||||
if ($body) {
|
||||
$errData = json_decode($body, true);
|
||||
foreach (($errData['error']['details'] ?? []) as $detail) {
|
||||
if (!empty($detail['retryDelay'])) {
|
||||
$parsed = intval(preg_replace('/\D/', '', $detail['retryDelay']));
|
||||
if ($parsed > 0) { $waitSec = min($parsed, 60); break; }
|
||||
}
|
||||
}
|
||||
|
||||
// Filet de sécurité : jamais laisser le cumul des attentes dépasser le budget
|
||||
if ((microtime(true) - $t0) + $waitSec >= $maxTotalElapsed) {
|
||||
EverLog::warn('AI retry budget exhausted, failing fast', ['elapsed' => microtime(true) - $t0]);
|
||||
break;
|
||||
}
|
||||
|
||||
EverLog::warn('AI rate-limited, retrying', ['attempt' => $attempt, 'wait_s' => $waitSec, 'code' => $lastCode]);
|
||||
|
||||
Reference in New Issue
Block a user