diff --git a/public/app.js b/public/app.js index 6bd1c1da..cea8be46 100644 --- a/public/app.js +++ b/public/app.js @@ -66,8 +66,9 @@ window.apiPerf = function() { })).sort((a, b) => b.totalMs - a.totalMs); console.table(rows); const hitRate = _apiPerf.calls ? Math.round(_apiPerf.cacheHits / _apiPerf.calls * 100) : 0; - console.log(`Cache: ${_apiPerf.cacheHits} hits / ${_apiPerf.calls} calls (${hitRate}% hit rate)`); - return { calls: _apiPerf.calls, avgMs: Math.round(_apiPerf.totalMs / (_apiPerf.calls - _apiPerf.cacheHits || 1)), cacheHits: _apiPerf.cacheHits, hitRate: hitRate + '%', endpoints: rows }; + const misses = _apiPerf.calls - _apiPerf.cacheHits; + console.log(`Cache: ${_apiPerf.cacheHits} hits / ${misses} misses (${hitRate}% hit rate)`); + return { calls: _apiPerf.calls, avgMs: Math.round(_apiPerf.totalMs / (misses || 1)), cacheHits: _apiPerf.cacheHits, cacheMisses: misses, cacheHitRate: hitRate, endpoints: rows }; }; function timeAgo(iso) { diff --git a/public/index.html b/public/index.html index b470ec86..904384bf 100644 --- a/public/index.html +++ b/public/index.html @@ -76,7 +76,7 @@
- + diff --git a/server.js b/server.js index c04048c8..37000f4d 100644 --- a/server.js +++ b/server.js @@ -46,6 +46,19 @@ class TTLCache { if (key.startsWith(prefix)) this.store.delete(key); } } + // Debounced invalidation — wait for burst of packets to settle + debouncedInvalidateAll() { + if (this._debounceTimer) return; // already scheduled + this._debounceTimer = setTimeout(() => { + this._debounceTimer = null; + this.invalidate('analytics:'); + this.invalidate('channels'); + this.invalidate('node:'); + this.invalidate('health:'); + this.invalidate('observers'); + this.invalidate('bulk-health'); + }, 5000); // batch invalidations over 5s window + } clear() { this.store.clear(); } get size() { return this.store.size; } } @@ -290,12 +303,7 @@ try { // Invalidate caches on new data - cache.invalidate('analytics:'); - cache.invalidate('channels'); - cache.invalidate('node:'); - cache.invalidate('health:'); - cache.invalidate('observers'); - cache.invalidate('bulk-health'); + cache.debouncedInvalidateAll(); const broadcastData = { id: packetId, raw: msg.raw, decoded, snr: msg.SNR, rssi: msg.RSSI, hash: msg.hash, observer: observerId }; broadcast({ type: 'packet', data: broadcastData }); @@ -634,12 +642,7 @@ app.post('/api/packets', (req, res) => { // Invalidate caches on new data - cache.invalidate('analytics:'); - cache.invalidate('channels'); - cache.invalidate('node:'); - cache.invalidate('health:'); - cache.invalidate('observers'); - cache.invalidate('bulk-health'); + cache.debouncedInvalidateAll(); broadcast({ type: 'packet', data: { id: packetId, decoded } });