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 } });