fix(ai): throttle now applies on ALL chunk iterations (incl. errors), delay bumped to 20s

This commit is contained in:
Michael committed 2026-02-21 21:56:16 +01:00
1 parent bcbea69d0a
commit 163d80dfe2
1 file changed
+32 -35
@@ -56,51 +56,48 @@ export function BulkAiAnalyzer() {
marge: r.totalMarge ? parseFloat(((r.totalMarge / (r.totalCa || 1)) * 100).toFixed(1)) : 0, marge: r.totalMarge ? parseFloat(((r.totalMarge / (r.totalCa || 1)) * 100).toFixed(1)) : 0,
})); }));
const res = await fetch("/api/ai/batch-analyze", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
rayon: chunk.rayon,
products: payloadProducts
})
});
if (!res.ok) {
const errText = await res.text();
console.error(`[BulkAiAnalyzer] Erreur HTTP ${res.status} sur le lot ${chunk.rayon}:`, errText);
setProgress(prev => ({ ...prev, errors: prev.errors + 1 }));
completed++;
continue;
}
try { try {
const data = await res.json(); const res = await fetch("/api/ai/batch-analyze", {
console.log(`[BulkAiAnalyzer] Response for ${chunk.rayon}:`, data); method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ rayon: chunk.rayon, products: payloadProducts })
});
if (data && Array.isArray(data.results)) { if (!res.ok) {
let applied = 0; const errText = await res.text();
data.results.forEach((reco: any) => { console.error(`[BulkAiAnalyzer] Erreur HTTP ${res.status} sur le lot ${chunk.rayon}:`, errText);
if (reco.codein && reco.recommandationGamme) { setProgress(prev => ({ ...prev, errors: prev.errors + 1 }));
setDraftGamme(reco.codein, reco.recommandationGamme);
const baseJustification = reco.justificationCourte || "Aucune explication.";
const justification = `Gamme ${reco.recommandationGamme} — ${baseJustification}`;
setInsight(reco.codein, justification, reco.isDuplicate ?? false);
applied++;
}
});
console.log(`[BulkAiAnalyzer] Applied ${applied} recommendations for ${chunk.rayon}`);
} else { } else {
console.warn(`[BulkAiAnalyzer] Unexpected response shape for ${chunk.rayon}:`, data); const data = await res.json();
console.log(`[BulkAiAnalyzer] Response for ${chunk.rayon}:`, data);
if (data && Array.isArray(data.results)) {
let applied = 0;
data.results.forEach((reco: any) => {
if (reco.codein && reco.recommandationGamme) {
setDraftGamme(reco.codein, reco.recommandationGamme);
const baseJustification = reco.justificationCourte || "Aucune explication.";
const justification = `Gamme ${reco.recommandationGamme} — ${baseJustification}`;
setInsight(reco.codein, justification, reco.isDuplicate ?? false);
applied++;
}
});
console.log(`[BulkAiAnalyzer] Applied ${applied} recommendations for ${chunk.rayon}`);
} else {
console.warn(`[BulkAiAnalyzer] Unexpected response shape for ${chunk.rayon}:`, data);
}
} }
} catch (e) { } catch (e) {
console.error(`[BulkAiAnalyzer] Failed to parse JSON for chunk ${chunk.rayon}:`, e); console.error(`[BulkAiAnalyzer] Failed fetch for chunk ${chunk.rayon}:`, e);
setProgress(prev => ({ ...prev, errors: prev.errors + 1 }));
} }
completed++; completed++;
// Respect OpenRouter free-tier rate limits — pause 3s before next chunk // Always wait 20s between chunks — free tier allows ~3 req/min
if (completed < chunks.length) { if (completed < chunks.length) {
await new Promise(resolve => setTimeout(resolve, 3000)); setProgress(prev => ({ ...prev, current: completed, message: `En attente... (lot ${completed}/${chunks.length})` }));
await new Promise(resolve => setTimeout(resolve, 20000));
} }
} }