Files
IdP/apps/frontend/lib/resilient-media-fetch.ts
2026-06-29 22:51:25 +03:00

61 lines
2.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { ensureApiGatewayReady, invalidateApiGatewayReady } from '@/lib/api';
const GATEWAY_RETRY_STATUS = new Set([502, 503, 504]);
const MEDIA_FETCH_MAX_ATTEMPTS = 8;
const MEDIA_SLOW_LOAD_WARN_MS = 8_000;
function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function warnSlowMediaLoad(label: string, startedAt: number, error: unknown) {
if (Date.now() - startedAt < MEDIA_SLOW_LOAD_WARN_MS) return;
const detail = error instanceof Error ? error.message : 'неизвестная ошибка';
console.warn(`[media] ${label}: не удалось загрузить за ${Math.round((Date.now() - startedAt) / 1000)} с (${detail})`);
}
export async function fetchMediaBlobWithRetry(
accessUrl: string,
token: string,
options?: { mimeType?: string; label?: string }
): Promise<Blob> {
const startedAt = Date.now();
const label = options?.label ?? 'изображение';
let lastError: unknown;
for (let attempt = 0; attempt < MEDIA_FETCH_MAX_ATTEMPTS; attempt += 1) {
try {
await ensureApiGatewayReady();
const response = await fetch(accessUrl, {
headers: { Authorization: `Bearer ${token}` },
cache: 'no-store'
});
if (GATEWAY_RETRY_STATUS.has(response.status) && attempt + 1 < MEDIA_FETCH_MAX_ATTEMPTS) {
invalidateApiGatewayReady();
await sleep(350 * (attempt + 1));
continue;
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const raw = await response.blob();
const mimeType = options?.mimeType;
if (mimeType && (!raw.type || raw.type === 'application/octet-stream')) {
return new Blob([await raw.arrayBuffer()], { type: mimeType });
}
return raw;
} catch (error) {
lastError = error;
if (attempt + 1 < MEDIA_FETCH_MAX_ATTEMPTS) {
await sleep(350 * (attempt + 1));
}
}
}
warnSlowMediaLoad(label, startedAt, lastError);
throw lastError instanceof Error ? lastError : new Error('Не удалось загрузить файл');
}