mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-07-02 23:51:40 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b3c0da8a94 | |||
| 3778ba9c95 | |||
| 2fc68c4452 | |||
| 2fc5da33d3 | |||
| 5d8c52d2e5 | |||
| 016c820207 | |||
| 93f437f937 | |||
| ad97c0fdd1 |
File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,17 @@ window.getParsedPath = function getParsedPath(p) {
|
||||
return p._parsedPath;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear cached _parsedPath/_parsedDecoded from a packet object.
|
||||
* Must be called after spreading a parent packet into an observation/child,
|
||||
* otherwise the child inherits stale cached values from the parent (issue #504).
|
||||
*/
|
||||
window.clearParsedCache = function clearParsedCache(p) {
|
||||
delete p._parsedPath;
|
||||
delete p._parsedDecoded;
|
||||
return p;
|
||||
};
|
||||
|
||||
window.getParsedDecoded = function getParsedDecoded(p) {
|
||||
if (p._parsedDecoded !== undefined) return p._parsedDecoded;
|
||||
var raw = p.decoded_json;
|
||||
|
||||
+5
-3
@@ -269,6 +269,7 @@
|
||||
if (obs) {
|
||||
expandedHashes.add(h);
|
||||
const obsPacket = {...data.packet, observer_id: obs.observer_id, observer_name: obs.observer_name, snr: obs.snr, rssi: obs.rssi, path_json: obs.path_json, timestamp: obs.timestamp, first_seen: obs.timestamp};
|
||||
clearParsedCache(obsPacket);
|
||||
selectPacket(obs.id, h, {packet: obsPacket, breakdown: data.breakdown, observations: data.observations}, obs.id);
|
||||
} else {
|
||||
selectPacket(data.packet.id, h, data);
|
||||
@@ -501,7 +502,7 @@
|
||||
await Promise.all(multiObs.map(async (p) => {
|
||||
try {
|
||||
const d = await api(`/packets/${p.hash}`);
|
||||
if (d?.observations) p._children = d.observations.map(o => ({...d.packet, ...o, _isObservation: true}));
|
||||
if (d?.observations) p._children = d.observations.map(o => clearParsedCache({...d.packet, ...o, _isObservation: true}));
|
||||
} catch {}
|
||||
}));
|
||||
// Flatten: replace grouped packets with individual observations
|
||||
@@ -837,7 +838,7 @@
|
||||
try {
|
||||
const data = await api(`/packets/${p.hash}`);
|
||||
if (data?.packet && data.observations) {
|
||||
p._children = data.observations.map(o => ({...data.packet, ...o, _isObservation: true}));
|
||||
p._children = data.observations.map(o => clearParsedCache({...data.packet, ...o, _isObservation: true}));
|
||||
p._fetchedData = data;
|
||||
}
|
||||
} catch {}
|
||||
@@ -1010,6 +1011,7 @@
|
||||
if (child) {
|
||||
const parentData = group._fetchedData;
|
||||
const obsPacket = parentData ? {...parentData.packet, observer_id: child.observer_id, observer_name: child.observer_name, snr: child.snr, rssi: child.rssi, path_json: child.path_json, timestamp: child.timestamp, first_seen: child.timestamp} : child;
|
||||
if (parentData) { clearParsedCache(obsPacket); }
|
||||
selectPacket(child.id, parentHash, {packet: obsPacket, breakdown: parentData?.breakdown, observations: parentData?.observations}, child.id);
|
||||
}
|
||||
}
|
||||
@@ -1979,7 +1981,7 @@
|
||||
if (!pkt) return;
|
||||
const group = packets.find(p => p.hash === hash);
|
||||
if (group && data.observations) {
|
||||
group._children = data.observations.map(o => ({...pkt, ...o, _isObservation: true}));
|
||||
group._children = data.observations.map(o => clearParsedCache({...pkt, ...o, _isObservation: true}));
|
||||
group._fetchedData = data;
|
||||
// Sort children based on current sort mode
|
||||
sortGroupChildren(group);
|
||||
|
||||
@@ -4411,6 +4411,61 @@ console.log('\n=== app.js: routeTypeName/payloadTypeName edge cases ===');
|
||||
});
|
||||
}
|
||||
|
||||
// ===== observation packet cache invalidation (issue #504) =====
|
||||
{
|
||||
console.log('\n=== Issue #504: observation packets must not inherit parent cache ===');
|
||||
|
||||
const helperSource = fs.readFileSync('public/packet-helpers.js', 'utf8');
|
||||
const ctx = vm.createContext({ window: {}, console, JSON, Array, Object });
|
||||
vm.runInContext(helperSource, ctx);
|
||||
const getParsedPath = ctx.window.getParsedPath;
|
||||
const getParsedDecoded = ctx.window.getParsedDecoded;
|
||||
const clearParsedCache = ctx.window.clearParsedCache;
|
||||
|
||||
test('clearParsedCache removes cached properties and returns the object', () => {
|
||||
const p = { path_json: '["A"]', decoded_json: '{"t":1}' };
|
||||
getParsedPath(p);
|
||||
getParsedDecoded(p);
|
||||
assert.ok(p._parsedPath !== undefined);
|
||||
assert.ok(p._parsedDecoded !== undefined);
|
||||
const ret = clearParsedCache(p);
|
||||
assert.strictEqual(ret, p, 'returns same object');
|
||||
assert.strictEqual(p._parsedPath, undefined);
|
||||
assert.strictEqual(p._parsedDecoded, undefined);
|
||||
});
|
||||
|
||||
test('observation packet gets its own path after cache invalidation', () => {
|
||||
const parent = { path_json: '["A","B"]', decoded_json: '{"type":"GRP_TXT"}' };
|
||||
// Prime the cache on parent
|
||||
getParsedPath(parent);
|
||||
getParsedDecoded(parent);
|
||||
|
||||
// Simulate spread + fix (like packets.js does after issue #504)
|
||||
const obs = { ...parent, path_json: '["X","Y","Z"]', decoded_json: '{"type":"TXT_MSG"}' };
|
||||
clearParsedCache(obs);
|
||||
|
||||
// getParsedPath re-parses from obs's own path_json
|
||||
const obsPath = getParsedPath(obs);
|
||||
assert.deepStrictEqual(obsPath, ['X', 'Y', 'Z'], 'obs gets its own path, not parent\'s');
|
||||
const obsDecoded = getParsedDecoded(obs);
|
||||
assert.deepStrictEqual(obsDecoded, { type: 'TXT_MSG' }, 'obs gets its own decoded, not parent\'s');
|
||||
});
|
||||
|
||||
test('observation packet path differs from parent after cache invalidation', () => {
|
||||
const parent = { path_json: '["hop1"]', decoded_json: '{"type":"REQ"}' };
|
||||
getParsedPath(parent);
|
||||
getParsedDecoded(parent);
|
||||
|
||||
const obs = { ...parent, path_json: '["hop2","hop3"]', decoded_json: '{"type":"GRP_TXT","text":"hi"}' };
|
||||
clearParsedCache(obs);
|
||||
|
||||
assert.notDeepStrictEqual(getParsedPath(obs), getParsedPath(parent),
|
||||
'observation must have different path from parent');
|
||||
assert.notDeepStrictEqual(getParsedDecoded(obs), getParsedDecoded(parent),
|
||||
'observation must have different decoded from parent');
|
||||
});
|
||||
}
|
||||
|
||||
// ===== SUMMARY =====
|
||||
Promise.allSettled(pendingTests).then(() => {
|
||||
console.log(`\n${'═'.repeat(40)}`);
|
||||
|
||||
Reference in New Issue
Block a user