fix(system): keep worker telemetry polling live

This commit is contained in:
DCCONSTRUCTIONS
2026-07-29 19:19:35 +03:00
parent 2678295ca7
commit 8e4891d608
3 changed files with 126 additions and 16 deletions
@@ -0,0 +1,45 @@
export interface SequentialPollingScheduler {
setTimeout(callback: () => void, delayMilliseconds: number): number;
clearTimeout(handle: number): void;
}
function createBrowserScheduler(): SequentialPollingScheduler {
return {
setTimeout: (callback, delayMilliseconds) =>
window.setTimeout(callback, delayMilliseconds),
clearTimeout: (handle) => window.clearTimeout(handle),
};
}
export function startSequentialPolling(
task: () => Promise<void>,
delayMilliseconds: number,
scheduler = createBrowserScheduler(),
): () => void {
let stopped = false;
let timer: number | null = null;
const run = async () => {
if (stopped) return;
try {
await task();
} catch {
// The caller owns error reporting. A transient failure must not stop polling.
}
if (stopped) return;
timer = scheduler.setTimeout(() => {
timer = null;
void run();
}, delayMilliseconds);
};
void run();
return () => {
stopped = true;
if (timer !== null) {
scheduler.clearTimeout(timer);
timer = null;
}
};
}
@@ -4,6 +4,7 @@ import {
fetchWorkerTelemetry,
type WorkerTelemetry,
} from "./workerTelemetry";
import { startSequentialPolling } from "./sequentialPolling";
import { normalizeWorkerTelemetryPollMilliseconds } from "./telemetryPollInterval";
export const DEFAULT_WORKER_TELEMETRY_POLL_MILLISECONDS = 3_000;
@@ -38,28 +39,31 @@ export function useWorkerTelemetry(
return;
}
const controller = new AbortController();
setLoading(true);
void fetchWorkerTelemetry(contourId, controller.signal)
.then((document) => {
const stopPolling = startSequentialPolling(async () => {
setLoading(true);
try {
const document = await fetchWorkerTelemetry(contourId, controller.signal);
if (controller.signal.aborted) return;
setTelemetry(document);
setError(null);
})
.catch((reason: unknown) => {
} catch (reason: unknown) {
if (controller.signal.aborted) return;
setError(reason instanceof Error ? reason.message : "Worker 006 не ответил.");
})
.finally(() => {
} finally {
if (!controller.signal.aborted) setLoading(false);
});
return () => controller.abort();
}, [contourId, enabled, externalRefreshGeneration, generation]);
useEffect(() => {
if (!enabled || loading) return;
const timer = window.setTimeout(refresh, normalizedPollMilliseconds);
return () => window.clearTimeout(timer);
}, [enabled, loading, normalizedPollMilliseconds, refresh]);
}
}, normalizedPollMilliseconds);
return () => {
stopPolling();
controller.abort();
};
}, [
contourId,
enabled,
externalRefreshGeneration,
generation,
normalizedPollMilliseconds,
]);
return { telemetry, loading, error, refresh };
}