fix and update

This commit is contained in:
lendry
2026-06-29 22:51:25 +03:00
parent 885b07d76b
commit 57cb58347b
30 changed files with 799 additions and 187 deletions

View 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('Не удалось загрузить файл');
}