fix: Add retry logic for OpenRouter 429 rate limit errors

- Retries up to 3 times with exponential backoff (2s, 4s, 8s)
- Also handles 503 service unavailable errors
- Logs retry attempts for debugging
- Only retries rate limit errors, other errors fail immediately
This commit is contained in:
2025-12-26 00:06:21 +01:00
parent 8ccd600dcb
commit 8cf51d4aea
3 changed files with 64 additions and 32 deletions

View File

@@ -71,13 +71,25 @@ Respond ONLY with valid JSON in this format:
"confidence": 0.85
}`;
/**
* Sleep helper for retry delays
*/
function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
/**
* Analyze whisky label with OpenRouter (Gemma 3 27B)
* Includes retry logic for 429 rate limit errors
*/
async function analyzeWithOpenRouter(base64Data: string, mimeType: string): Promise<{ data: any; apiTime: number }> {
const client = getOpenRouterClient();
const startApi = performance.now();
const maxRetries = 3;
let lastError: any = null;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await client.chat.completions.create({
model: OPENROUTER_VISION_MODEL,
messages: [
@@ -115,6 +127,26 @@ async function analyzeWithOpenRouter(base64Data: string, mimeType: string): Prom
data: JSON.parse(jsonStr),
apiTime: endApi - startApi,
};
} catch (error: any) {
lastError = error;
const status = error?.status || error?.response?.status;
// Only retry on 429 (rate limit) or 503 (service unavailable)
if (status === 429 || status === 503) {
const delay = Math.pow(2, attempt) * 1000; // 2s, 4s, 8s
console.log(`[OpenRouter] Rate limited (${status}), retry ${attempt}/${maxRetries} in ${delay}ms...`);
await sleep(delay);
continue;
}
// Other errors - don't retry
throw error;
}
}
// All retries exhausted
throw lastError || new Error('OpenRouter request failed after retries');
}
/**

View File

@@ -37,4 +37,4 @@ export function getOpenRouterClient(): OpenAI {
}
// Default OpenRouter model for vision tasks
export const OPENROUTER_VISION_MODEL = 'google/gemma-3-27b-it';
export const OPENROUTER_VISION_MODEL = 'google/gemma-3-27b-it:free';

File diff suppressed because one or more lines are too long