From e58879830f794a0173de373e2ae79febb18ca705 Mon Sep 17 00:00:00 2001 From: you Date: Sat, 21 Mar 2026 21:34:05 +0000 Subject: [PATCH] fix: stop channels page from spamming API requests The channels WS handler was calling invalidateApiCache() before loadChannels()/refreshMessages(), which nuked the cache and forced network fetches. Combined with the global WS onmessage handler also invalidating /channels every 5s, this created excessive API traffic when sitting idle on the channels page. Changes: - channels.js: Remove invalidateApiCache calls from WS handler, use bust:true parameter instead to bypass cache only when WS triggers - channels.js: Add bust parameter to loadChannels() and refreshMessages() - app.js: Remove /channels from global WS cache invalidation (channels page manages its own cache busting via its dedicated WS handler) --- public/app.js | 1 - public/channels.js | 16 ++++++---------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/public/app.js b/public/app.js index 30e41cfd..844cf4a1 100644 --- a/public/app.js +++ b/public/app.js @@ -215,7 +215,6 @@ function connectWS() { api._invalidateTimer = null; invalidateApiCache('/stats'); invalidateApiCache('/nodes'); - invalidateApiCache('/channels'); }, 5000); } wsListeners.forEach(fn => fn(msg)); diff --git a/public/channels.js b/public/channels.js index b4406dda..73923ea4 100644 --- a/public/channels.js +++ b/public/channels.js @@ -377,12 +377,8 @@ return m.type === 'message' || (m.type === 'packet' && m.data?.decoded?.header?.payloadTypeName === 'GRP_TXT'); }); if (dominated) { - invalidateApiCache('/channels'); - loadChannels(true); - if (selectedHash) { - invalidateApiCache('/channels/' + encodeURIComponent(selectedHash) + '/messages'); - refreshMessages(); - } + loadChannels(true, true); + if (selectedHash) refreshMessages(true); } }); } @@ -401,11 +397,11 @@ if (panel) panel.remove(); } - async function loadChannels(silent) { + async function loadChannels(silent, bust) { try { const rp = RegionFilter.getRegionParam(); const qs = rp ? '?region=' + encodeURIComponent(rp) : ''; - const data = await api('/channels' + qs, { ttl: CLIENT_TTL.channels }); + const data = await api('/channels' + qs, { ttl: CLIENT_TTL.channels, bust: !!bust }); channels = (data.channels || []).sort((a, b) => (b.lastActivity || '').localeCompare(a.lastActivity || '')); renderChannelList(); } catch (e) { @@ -474,13 +470,13 @@ } } - async function refreshMessages() { + async function refreshMessages(bust) { if (!selectedHash) return; const msgEl = document.getElementById('chMessages'); if (!msgEl) return; const wasAtBottom = msgEl.scrollHeight - msgEl.scrollTop - msgEl.clientHeight < 60; try { - const data = await api(`/channels/${encodeURIComponent(selectedHash)}/messages?limit=200`, { ttl: CLIENT_TTL.channelMessages }); + const data = await api(`/channels/${encodeURIComponent(selectedHash)}/messages?limit=200`, { ttl: CLIENT_TTL.channelMessages, bust: !!bust }); const newMsgs = data.messages || []; // #92: Use message ID/hash for change detection instead of count + timestamp var _getLastId = function (arr) { var m = arr.length ? arr[arr.length - 1] : null; return m ? (m.id || m.packetId || m.timestamp || '') : ''; };