fix and update
This commit is contained in:
60
apps/frontend/lib/resilient-media-fetch.ts
Normal file
60
apps/frontend/lib/resilient-media-fetch.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
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('Не удалось загрузить файл');
|
||||
}
|
||||
Reference in New Issue
Block a user