feat(cache): implement integrity checks for cached events and waveforms
- Added `waveform_key` and `event_timestamp` columns to `CachedEvent` and `CachedWaveform` for integrity verification. - Implemented logic to flush the cache when a mismatch in (waveform_key, event_timestamp) is detected during event and waveform updates. - Enhanced `set_events` and `set_waveform` methods to check for mismatches and trigger cache eviction as necessary. - Introduced a new `LiveCache` class to manage in-memory caching of live device data, separating it from the server logic for better testability. - Added tests to verify the correctness of cache invalidation logic, particularly for post-erase key reuse scenarios. - Updated web application to include a "Force refresh" toggle, allowing users to bypass the cache and re-fetch data from the device.
This commit is contained in:
+51
-1
@@ -609,6 +609,36 @@
|
||||
.section-btn:hover { color: var(--text); }
|
||||
.section-btn.active { background: var(--blue); color: #fff; }
|
||||
|
||||
/* ── Force-refresh toggle ── */
|
||||
.force-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 4px 10px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
background: var(--bg);
|
||||
cursor: pointer;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: var(--text-dim);
|
||||
user-select: none;
|
||||
white-space: nowrap;
|
||||
transition: background 0.12s, color 0.12s, border-color 0.12s;
|
||||
}
|
||||
.force-toggle input { margin: 0; cursor: pointer; }
|
||||
.force-toggle:hover { color: var(--text); }
|
||||
.force-toggle.active {
|
||||
background: rgba(248, 81, 73, 0.18);
|
||||
border-color: #f85149;
|
||||
color: #ff7b72;
|
||||
}
|
||||
.force-toggle .ft-dot {
|
||||
width: 6px; height: 6px; border-radius: 50%;
|
||||
background: var(--text-mute);
|
||||
}
|
||||
.force-toggle.active .ft-dot { background: #f85149; box-shadow: 0 0 6px #f85149; }
|
||||
|
||||
/* ── Section containers ── */
|
||||
#section-live, #section-db {
|
||||
display: flex;
|
||||
@@ -654,6 +684,13 @@
|
||||
<button class="section-btn active" onclick="switchSection('live')">Live Device</button>
|
||||
<button class="section-btn" onclick="switchSection('db')">Database</button>
|
||||
</div>
|
||||
<div class="hdr-sep"></div>
|
||||
<label class="force-toggle" id="force-toggle"
|
||||
title="Bypass server cache and dedup. Forces a fresh download from the device on every live request — useful when the device has been erased and the cache is showing stale events.">
|
||||
<input type="checkbox" id="force-cb" onchange="onForceToggle()">
|
||||
<span class="ft-dot"></span>
|
||||
<span>Force refresh</span>
|
||||
</label>
|
||||
</header>
|
||||
|
||||
<!-- ════════════════════════════════════════════════════════════════
|
||||
@@ -1214,8 +1251,21 @@ function setCfgStatus(msg, cls = '') {
|
||||
el.className = cls;
|
||||
}
|
||||
|
||||
// "Force refresh" override — when enabled, every live-device request is
|
||||
// sent with ?force=true so the server bypasses its in-memory + persistent
|
||||
// caches and re-reads from the device. Manual escape hatch for cases where
|
||||
// the cache has gone stale (e.g. post-erase key reuse — see ach_server.py
|
||||
// and sfm/cache.py for the eviction logic).
|
||||
let forceRefresh = false;
|
||||
|
||||
function onForceToggle() {
|
||||
forceRefresh = document.getElementById('force-cb').checked;
|
||||
document.getElementById('force-toggle').classList.toggle('active', forceRefresh);
|
||||
}
|
||||
|
||||
function deviceParams() {
|
||||
return `host=${encodeURIComponent(devHost())}&tcp_port=${devPort()}`;
|
||||
const base = `host=${encodeURIComponent(devHost())}&tcp_port=${devPort()}`;
|
||||
return forceRefresh ? `${base}&force=true` : base;
|
||||
}
|
||||
|
||||
// ── Section switching ─────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user