차unked 백업 업로더가 Discourse 요청 속도 제한 초과

고객 중 한 명이 관리자 UI를 통해 로컬 Discourse 백업을 업로드할 때 재현 가능한 문제에 직면했습니다.

백업 업로더는 고정된 5MB 청크를 사용하며, 충분히 빠른 연결 환경에서는 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년에 작성되었으나 빠르게 방향이 어긋나버린 이 토픽을 찾았는데, 정확히 동일한 문제인 것 같습니다.