huge optimizations

This commit is contained in:
KingKDot
2026-06-08 22:33:34 -05:00
parent 9a1fc96e2b
commit d6ad2cadea
21 changed files with 649 additions and 72 deletions
+47 -4
View File
@@ -4,6 +4,8 @@ import { digestData } from "./utils.js";
const POLL_INTERVAL_MS = 5000;
const FALLBACK_POLL_MS = 30000;
const PREF_REFRESH_KEY = "overlord_refresh_interval_seconds";
const REALTIME_MIN_LOAD_MS = 1500;
const REALTIME_CHURN_WINDOW_MS = 5000;
let pollTimer = null;
let render = () => {};
let lastClientData = null;
@@ -12,6 +14,12 @@ const PAGE_CACHE_LIMIT = 8;
let dashboardWs = null;
let dashboardWsConnected = false;
let wsReconnectTimer = null;
let realtimeLoadTimer = null;
let lastRealtimeLoadAt = 0;
let lastRealtimeEventAt = 0;
let realtimeEventCount = 0;
let realtimeForce = false;
let realtimeReorder = false;
const manuallyDisconnecting = new Set();
function stopDashboardRealtime() {
@@ -19,6 +27,8 @@ function stopDashboardRealtime() {
pollTimer = null;
clearTimeout(wsReconnectTimer);
wsReconnectTimer = null;
clearTimeout(realtimeLoadTimer);
realtimeLoadTimer = null;
if (dashboardWs) {
try {
dashboardWs.onopen = null;
@@ -32,6 +42,38 @@ function stopDashboardRealtime() {
dashboardWsConnected = false;
}
function noteRealtimeEvent() {
const now = Date.now();
if (now - lastRealtimeEventAt > REALTIME_CHURN_WINDOW_MS) {
realtimeEventCount = 0;
}
lastRealtimeEventAt = now;
realtimeEventCount += 1;
}
function isRealtimeChurnActive() {
return Date.now() - lastRealtimeEventAt < REALTIME_CHURN_WINDOW_MS && realtimeEventCount > 5;
}
function scheduleRealtimeLoad(options = {}) {
noteRealtimeEvent();
realtimeForce = realtimeForce || !!options.force;
realtimeReorder = realtimeReorder || options.reorder !== false;
if (realtimeLoadTimer) return;
const elapsed = Date.now() - lastRealtimeLoadAt;
const delay = Math.max(0, REALTIME_MIN_LOAD_MS - elapsed);
realtimeLoadTimer = setTimeout(() => {
realtimeLoadTimer = null;
lastRealtimeLoadAt = Date.now();
const force = realtimeForce;
const reorder = realtimeReorder;
realtimeForce = false;
realtimeReorder = false;
loadWithOptions({ force, reorder });
}, delay);
}
function bindDashboardPagehideCleanup() {
window.removeEventListener("pagehide", stopDashboardRealtime);
window.addEventListener("pagehide", stopDashboardRealtime);
@@ -101,6 +143,7 @@ async function prefetchClientPage(page) {
}
function prefetchAdjacentPages(data) {
if (isRealtimeChurnActive()) return;
const totalPages = Math.max(1, Math.ceil((Number(data.total) || 0) / (Number(data.pageSize) || state.pageSize || 1)));
const current = Number(data.page) || state.page;
if (current < totalPages) prefetchClientPage(current + 1);
@@ -219,16 +262,16 @@ function connectDashboardWs() {
try {
const msg = typeof event.data === "string" ? JSON.parse(event.data) : null;
if (msg && msg.type === "clients_changed") {
loadWithOptions({ force: false, reorder: true });
scheduleRealtimeLoad({ force: false, reorder: true });
return;
}
if (msg && msg.type === "client_event") {
if (msg.event === "client_offline" && manuallyDisconnecting.has(msg.clientId)) {
manuallyDisconnecting.delete(msg.clientId);
loadWithOptions({ force: true });
scheduleRealtimeLoad({ force: true, reorder: true });
} else {
moveClientCardImmediately(msg);
loadWithOptions({ force: false, reorder: true });
if (!isRealtimeChurnActive()) moveClientCardImmediately(msg);
scheduleRealtimeLoad({ force: false, reorder: true });
}
}
} catch {}
+61
View File
@@ -780,6 +780,67 @@ function updateMetrics(data, debug) {
}
}
const internalTasksList = document.getElementById("internal-tasks");
if (internalTasksList) {
const tasks = Array.isArray(data.internal?.tasks) ? data.internal.tasks : [];
if (tasks.length > 0) {
internalTasksList.innerHTML = tasks
.map((task) => `
<div class="bg-slate-800/50 rounded p-3 min-w-0">
<div class="text-xs text-slate-400 mb-2 truncate" title="${escapeHtml(task.task)}">
${escapeHtml(task.task)}
</div>
<div class="grid grid-cols-2 gap-x-3 gap-y-1 text-xs">
<span class="text-slate-500">p95</span>
<span class="font-semibold text-right">${formatMs(task.durationP95 || 0)}</span>
<span class="text-slate-500">avg</span>
<span class="font-semibold text-right">${formatMs(task.durationAvg || 0)}</span>
<span class="text-slate-500">max</span>
<span class="font-semibold text-right">${formatMs(task.durationMax || 0)}</span>
<span class="text-slate-500">runs/min</span>
<span class="font-semibold text-right">${Number(task.countLastMinute || 0).toLocaleString()}</span>
</div>
</div>
`)
.join("");
} else {
internalTasksList.innerHTML =
'<div class="text-slate-500 col-span-full text-center py-4">No internal job samples yet</div>';
}
}
const retainedStateList = document.getElementById("retained-state");
if (retainedStateList) {
const retained = data.diagnostics?.retained || {};
const entries = Object.entries(retained)
.filter(([, value]) => typeof value === "number" || typeof value === "boolean")
.sort(([a], [b]) => a.localeCompare(b));
if (entries.length > 0) {
retainedStateList.innerHTML = entries
.map(([key, value]) => {
const displayValue = key.toLowerCase().includes("bytes")
? formatBytes(Number(value || 0))
: typeof value === "boolean"
? value ? "yes" : "no"
: Number(value || 0).toLocaleString();
return `
<div class="bg-slate-800/50 rounded p-3 min-w-0">
<div class="text-xs text-slate-500 mb-1 truncate" title="${escapeHtml(key)}">
${escapeHtml(key)}
</div>
<div class="text-sm font-semibold truncate" title="${escapeHtml(displayValue)}">
${escapeHtml(displayValue)}
</div>
</div>
`;
})
.join("");
} else {
retainedStateList.innerHTML =
'<div class="text-slate-500 col-span-full text-center py-4">No retained state counters yet</div>';
}
}
const commandTypesList = document.getElementById("command-types");
if (Object.keys(data.commands.byType).length > 0) {
const topCommands = Object.entries(data.commands.byType)
@@ -36,6 +36,7 @@ async function triggerAgentThumbnail(clientId) {
const res = await fetch(`/api/clients/${encodeURIComponent(clientId)}/thumbnail`, {
method: "POST",
credentials: "include",
headers: { "X-Overlord-Thumbnail-Source": "dashboard" },
});
if (!res.ok) return null;
return await res.json().catch(() => null);