fix(report-ui): ретрай docx-preflight против 502-гонки сразу после ready (#2353)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 3m26s
Deploy / deploy (push) Successful in 1m19s

This commit is contained in:
bot-backend 2026-07-04 00:03:12 +00:00
parent 7ebeddc2bc
commit c778e4c85d

View file

@ -122,17 +122,30 @@ function triggerAnchorDownload(cad: string, format: ReportFormat): void {
async function triggerReportDownload( async function triggerReportDownload(
cad: string, cad: string,
format: ReportFormat, format: ReportFormat,
onError: () => void, onError: (message: string) => void,
): Promise<void> { ): Promise<void> {
if (format === "pdf") { if (format === "pdf") {
triggerAnchorDownload(cad, "pdf"); triggerAnchorDownload(cad, "pdf");
return; return;
} }
try { try {
const res = await fetch(downloadUrl(cad, "docx"), { method: "HEAD" }); let res = await fetch(downloadUrl(cad, "docx"), { method: "HEAD" });
// Любой не-OK (404 легаси-рана, 5xx) — не даём <a> молча скачать страницу ошибки. // 5xx сразу после status=ready — транзиентная proxy-гонка (стресс-свип
// 2026-07-04: первый HEAD после ready ловил 502, ретрей через ~1.5с — 200).
// Один ретрай, прежде чем показывать пользователю ошибку.
if (!res.ok && res.status !== 404) {
await new Promise((r) => setTimeout(r, 1500));
res = await fetch(downloadUrl(cad, "docx"), { method: "HEAD" });
}
if (res.status === 404) {
// Легаси-ран без docx_path — честная просьба пересобрать.
onError("Пересоберите отчёт — DOCX для старого прогона отсутствует");
return;
}
if (!res.ok) { if (!res.ok) {
onError(); // Устойчивый не-OK (5xx и после ретрая) — не даём <a> молча скачать
// страницу ошибки, но и НЕ просим пересобрать (файл скорее всего цел).
onError("Не удалось скачать отчёт — повторите через минуту");
return; return;
} }
} catch { } catch {
@ -160,10 +173,8 @@ export function useFullReport(cad: string): UseFullReportResult {
const pendingFormatRef = useRef<ReportFormat>("pdf"); const pendingFormatRef = useRef<ReportFormat>("pdf");
// Стабильный колбэк ошибки docx-download'а для triggerReportDownload. // Стабильный колбэк ошибки docx-download'а для triggerReportDownload.
const handleDownloadError = useCallback(() => { const handleDownloadError = useCallback((message: string) => {
setDownloadError( setDownloadError(message);
"Пересоберите отчёт — DOCX для старого прогона отсутствует",
);
}, []); }, []);
// ── POST enqueue ──────────────────────────────────────────────────────────── // ── POST enqueue ────────────────────────────────────────────────────────────