L’un de nos clients a rencontré un problème reproductible lors de l’envoi d’une sauvegarde Discourse locale via l’interface d’administration.
L’outil d’envoi de sauvegardes utilise des blocs fixes de 5 Mo et, sur une connexion suffisamment rapide, peut générer suffisamment de requêtes pour dépasser la limite de taux de requêtes au niveau de l’application de Discourse elle-même. Dans ce cas, le serveur renvoie un HTTP 429, mais l’outil d’envoi par blocs ne réessaie pas les réponses 429 et ne respecte pas l’en-tête Retry-After. En conséquence, l’envoi complet de la sauvegarde échoue.
Les réponses non 2xx sont converties en erreur :
if (ev.target.status < 200 || ev.target.status >= 300) {
const error = new Error("Non 2xx");
error.source = ev.target;
reject(error);
return;
}
La logique de réessai est la suivante :
_shouldRetry(err) {
if (err.source && typeof err.source.status === "number") {
const { status } = err.source;
return (
status === 0 ||
status === 409 ||
status === 423 ||
(status >= 500 && status < 600)
);
}
return false;
}
Le HTTP 429 n’est donc explicitement pas réessayable.
Une seule réponse 429 suffit pour que la promesse d’envoi par blocs échoue, déclenchant éventuellement upload-error pour l’envoi complet de la sauvegarde.
Il n’y a également aucune gestion de l’en-tête de réponse Retry-After.
J’ai trouvé ce sujet de 2021 qui a déraillé assez rapidement, mais qui semble être exactement le même problème