fix(system): keep worker telemetry polling live
This commit is contained in:
@@ -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 };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user