Files
nahodka-front/src/hooks/useTranscodingStatusPolling.js
2026-10-06 01:00:10 +03:00

79 lines
2.8 KiB
JavaScript
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 { useState, useEffect, useRef } from 'react';
import { apiFetch } from '../api/apiClient';
import { API_URL } from '../config/authConstants';
const TERMINAL_STATUSES = ['READY', 'FAILED'];
const POLL_INTERVAL_MS = 3000;
const MAX_POLL_ATTEMPTS = 100;
/**
* Поллинг статуса транскодинга медиа.
* @param {number|string} advertisingId — id сущности
* @param {boolean} enabled — включать поллинг
* @param {string} [path="ads"] — сегмент пути (например, "ads" или "fullscreen-ads")
* @returns {string} транскодинг-статус и его производные (PROCESSING/READY/FAILED/TIMEOUT)
*/
export function useTranscodingStatusPolling(advertisingId, enabled, path = "ads") {
const [status, setStatus] = useState('PROCESSING');
const attemptsRef = useRef(0);
useEffect(() => {
if (!enabled || !advertisingId) {
// Статус предыдущей сущности нельзя переносить на следующую: иначе
// новый элемент сразу получит терминальный статус и polling сразу выключится.
setStatus('PROCESSING');
return;
}
attemptsRef.current = 0;
let cancelled = false;
let timeoutId;
const poll = async () => {
if (cancelled) return;
try {
const res = await apiFetch(`${API_URL}/api/v1/admin/${path}/${advertisingId}/status`);
if (!res.ok) {
throw new Error(`Status check failed: ${res.status}`);
}
const data = await res.json();
if (cancelled) return;
setStatus(data.transcodingStatus ?? 'PROCESSING');
attemptsRef.current += 1;
const isTerminal = TERMINAL_STATUSES.includes(data.transcodingStatus);
const exceededAttempts = attemptsRef.current >= MAX_POLL_ATTEMPTS;
if (!isTerminal && !exceededAttempts) {
timeoutId = setTimeout(poll, POLL_INTERVAL_MS);
} else if (exceededAttempts && !isTerminal) {
setStatus('TIMEOUT');
}
} catch (err) {
if (cancelled) return;
console.warn('Status poll failed, retrying', err);
// Ошибки тоже тратят попытки, иначе MAX_POLL_ATTEMPTS недостижим
// и запрос к несуществующему эндпоинту будет повторяться вечно.
attemptsRef.current += 1;
if (attemptsRef.current >= MAX_POLL_ATTEMPTS) {
setStatus('TIMEOUT');
return;
}
timeoutId = setTimeout(poll, POLL_INTERVAL_MS);
}
};
poll();
return () => {
cancelled = true;
clearTimeout(timeoutId);
};
}, [advertisingId, enabled, path]);
return status;
}