Один из наших пользователей столкнулся с воспроизводимой проблемой при загрузке локального резервного копирования Discourse через административный интерфейс.
Модуль загрузки резервных копий использует фиксированные блоки по 5 МБ и, при достаточно быстром соединении, может генерировать столько запросов, что превышается собственный на уровне приложения лимит частоты запросов Discourse. Когда это происходит, сервер возвращает HTTP 429, но модуль загрузки блоками не повторяет запросы при ответе 429 и не учитывает заголовок Retry-After. В результате загрузка всего резервного копирования завершается ошибкой.
Ответы, отличные от 2xx, преобразуются в ошибку:
if (ev.target.status < 200 || ev.target.status >= 300) {
const error = new Error("Non 2xx");
error.source = ev.target;
reject(error);
return;
}
Логика повтора выглядит так:
_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;
}
Таким образом, HTTP 429 явно не является повторным.
Достаточно одного ответа 429, чтобы промис загрузки блока завершился с ошибкой, что в конечном итоге приводит к срабатыванию события upload-error для всей загрузки резервной копии.
Также отсутствует обработка заголовка ответа Retry-After.
Я нашел эту тему от 2021 года, которая довольно быстро ушла в сторону, но, похоже, описывает ровно ту же проблему