Cache certificate inventory and stop refreshPendingProxies from re-triggering a full refresh

This commit is contained in:
marvin
2026-09-19 22:24:13 -04:00
parent 8e6a5f9196
commit 578d39a3ad
6 changed files with 29 additions and 6 deletions
+11 -1
View File
@@ -533,12 +533,22 @@ function render() {
// --- Data refresh helpers ------------------------------------------------------------------
async function refresh() { const requests = [api("/api/sites"), api("/api/proxies"), api("/api/redirects"), api("/api/streams"), api("/api/access-lists"), canAdmin() ? api("/api/groups") : Promise.resolve([]), api("/api/dashboard"), api("/api/certificates")]; const results = await Promise.allSettled(requests); results.forEach((result, index) => { if (result.status !== "fulfilled") return; const keys = ["sites", "proxies", "redirects", "streams", "accessLists", "groups", "dashboard", "certificates"]; state[keys[index]] = result.value; }); state.loaded = true; render(); window.renderExtendedViews?.(); const pending = state.proxies.filter(proxy => proxy.enabled !== false && !proxy.upstream).map(proxy => proxy.id); if (pending.length && !state.pendingProxyRefresh) { state.pendingProxyRefresh = true; refreshPendingProxies(pending).finally(() => { state.pendingProxyRefresh = false; }); } }
// Polls just /api/proxies for upstream health that wasn't ready yet on the last refresh() --
// e.g. right after a page load or a new proxy, before its first health check has completed.
// This used to call the full refresh() (all 8 endpoints, including two redundant certificate
// walks via /api/dashboard + /api/certificates), up to 3 times in a row -- meaning a single
// pending proxy could quietly trigger 3 extra full-app refetches over 6 seconds. Since all it
// actually needs is fresh upstream status, it now re-fetches only /api/proxies.
async function refreshPendingProxies(ids = []) {
const pending = new Set(ids.map(String));
for (const delay of [1000, 2000, 3000]) {
if (!pending.size) return;
await new Promise(resolve => setTimeout(resolve, delay));
await refresh();
try {
state.proxies = await api("/api/proxies");
render();
window.renderExtendedViews?.();
} catch { /* Keep the last-known proxy list if this poll fails; the next delay tries again. */ }
for (const proxy of state.proxies) if (pending.has(String(proxy.id)) && proxy.upstream) pending.delete(String(proxy.id));
}
}
+2 -2
View File
@@ -8,7 +8,7 @@
<title>Site Gateway</title>
<meta name="description" content="Host sites, proxy services, and manage HTTPS from one simple dashboard.">
<link rel="icon" type="image/png" href="/site-gateway-icon-approved.png">
<link rel="stylesheet" href="/styles.css?v=0.16.40">
<link rel="stylesheet" href="/styles.css?v=0.16.41">
</head>
<!-- ================================================================
@@ -432,6 +432,6 @@
<div id="toast" class="toast" role="status"></div>
<div id="update-banner" class="update-banner hidden" role="status"><span>A new version of Site Gateway is available.</span><div class="update-banner-actions"><button id="update-banner-refresh" class="button primary">Refresh</button><button id="update-banner-dismiss" class="text-button">Dismiss</button></div></div>
<!-- App scripts: core (app.js) then extended views/admin (features.js) -->
<script src="/app.js?v=0.16.40" defer></script><script src="/features.js?v=0.16.40" defer></script><script src="/select-enhance.js?v=0.16.40" defer></script>
<script src="/app.js?v=0.16.41" defer></script><script src="/features.js?v=0.16.41" defer></script><script src="/select-enhance.js?v=0.16.41" defer></script>
</body>
</html>