This commit is contained in:
Mateusz Gruszczyński committed 2026-10-13 00:57:19 +02:00
1 parent 81ab39e70a
commit 101df02a5f
45 files changed
+1148 -2277

No files matched your search

+28 -21
View File
@@ -1,5 +1,3 @@
// Single scheduler for all authenticated dashboard polling. SSE is controlled here
// but remains one native EventSource with its own browser reconnect behavior.
const REFRESH_DEFAULTS = Object.freeze({
live_enabled: true, overview_seconds: 2, traffic_seconds: 5,
cache_seconds: 5, system_info_seconds: 60
@@ -49,13 +47,11 @@ const rustProxyRefresh = (() => {
const controller = new AbortController(), generation = task.generation, epoch = authEpoch;
const panelAtStart = panel, tabAtStart = settingsTab;
task.controller = controller;
// A manual request remains valid with Live switched off, but not in a stale view.
const isCurrent = () => authenticated && epoch === authEpoch && !controller.signal.aborted &&
generation === task.generation && (manual ? panel === panelAtStart && settingsTab === tabAtStart : allowed(task));
const promise = Promise.resolve().then(() => task.run({ signal: controller.signal, isCurrent }));
task.inFlight = promise.catch(error => {
if (error?.name !== "AbortError" && isCurrent()) {
// A failure is isolated to this source; other timers continue.
if (task.onError) task.onError(error);
else console.warn(`Refresh ${task.id} failed:`, error);
}
@@ -161,19 +157,26 @@ const rustProxyRefresh = (() => {
if (!task) return Promise.reject(new Error(`Unknown refresh task: ${id}`));
return execute(task, true);
}
register("status-full", { interval: () => 0, run: async ({ signal, isCurrent }) => {
const value = await api("/api/status", { signal });
if (isCurrent()) renderStatus(value, true);
}});
register("status-fallback", { interval: () => options.overview_seconds, active: () => !liveConnected && (liveFallback || typeof EventSource === "undefined"), run: async ({ signal, isCurrent }) => {
const value = await api("/api/status?view=live", { signal });
if (isCurrent()) renderLiveStatus(value);
}, onError: error => { if (error?.status !== 401) $("connection-label").textContent = t("disconnected"); }});
register("logs-fallback", { interval: () => options.overview_seconds, active: () => !liveConnected && (liveFallback || typeof EventSource === "undefined"), run: async ({ signal, isCurrent }) => {
const value = await api("/api/logs", { signal });
if (isCurrent()) renderLogs(value);
}});
register("system-info", { interval: () => options.system_info_seconds,
register("status-full", {
interval: () => 0, run: async ({ signal, isCurrent }) => {
const value = await api("/api/status", { signal });
if (isCurrent()) renderStatus(value, true);
}
});
register("status-fallback", {
interval: () => options.overview_seconds, active: () => !liveConnected && (liveFallback || typeof EventSource === "undefined"), run: async ({ signal, isCurrent }) => {
const value = await api("/api/status?view=live", { signal });
if (isCurrent()) renderLiveStatus(value);
}, onError: error => { if (error?.status !== 401) $("connection-label").textContent = t("disconnected"); }
});
register("logs-fallback", {
interval: () => options.overview_seconds, active: () => !liveConnected && (liveFallback || typeof EventSource === "undefined"), run: async ({ signal, isCurrent }) => {
const value = await api("/api/logs", { signal });
if (isCurrent()) renderLogs(value);
}
});
register("system-info", {
interval: () => options.system_info_seconds,
active: () => panel === "overview" || (panel === "settings" && ["system-info", "cache"].includes(settingsTab)),
run: async ({ signal, isCurrent }) => {
const value = await api("/api/system-info", { signal });
@@ -183,11 +186,15 @@ const rustProxyRefresh = (() => {
window.rustProxySettings?.render();
}
});
register("tunnels", { interval: () => 2, active: () => !!$("tunnels-dialog")?.open,
run: async context => { await loadTunnels(context); } });
return { register, manual, start, stop, sync, update, setPanel, setSettingsTab,
register("tunnels", {
interval: () => 2, active: () => !!$("tunnels-dialog")?.open,
run: async context => { await loadTunnels(context); }
});
return {
register, manual, start, stop, sync, update, setPanel, setSettingsTab,
suspendForSessionValidation, completeSessionValidation,
current: () => ({ ...options }), diagnostics: () => [...tasks.values()].map(t => ({ id: t.id, enabled: t.enabled, inFlight: !!t.inFlight, scheduled: t.timer !== null })) };
current: () => ({ ...options }), diagnostics: () => [...tasks.values()].map(t => ({ id: t.id, enabled: t.enabled, inFlight: !!t.inFlight, scheduled: t.timer !== null }))
};
})();
window.rustProxyRefresh = rustProxyRefresh;