From 1450bc928bc1dc8488e7448471122dba321a42bc Mon Sep 17 00:00:00 2001 From: you Date: Sun, 22 Mar 2026 18:55:22 +0000 Subject: [PATCH] Packets page: O(1) hash dedup via Map index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit packets.find(g => g.hash === h) was O(n) and could race with loadPackets replacing the array. hashIndex Map stays in sync — rebuilt on API fetch, updated on WS insert. Prevents duplicate rows for same hash in grouped mode. --- public/index.html | 2 +- public/packets.js | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/public/index.html b/public/index.html index cfb2589..0627581 100644 --- a/public/index.html +++ b/public/index.html @@ -84,7 +84,7 @@ - + diff --git a/public/packets.js b/public/packets.js index 3390c09..32ac60f 100644 --- a/public/packets.js +++ b/public/packets.js @@ -3,6 +3,7 @@ (function () { let packets = []; + let hashIndex = new Map(); // hash → packet group for O(1) dedup // Resolve observer_id to friendly name from loaded observers list function obsName(id) { @@ -297,7 +298,7 @@ // Update existing groups or create new ones for (const p of filtered) { const h = p.hash; - const existing = packets.find(g => g.hash === h); + const existing = hashIndex.get(h); if (existing) { existing.count = (existing.count || 1) + 1; existing.observation_count = (existing.observation_count || 1) + 1; @@ -316,7 +317,7 @@ } } else { // New group - packets.unshift({ + const newGroup = { hash: h, count: 1, observer_count: 1, @@ -327,7 +328,9 @@ payload_type: p.payload_type, raw_hex: p.raw_hex, decoded_json: p.decoded_json, - }); + }; + packets.unshift(newGroup); + if (h) hashIndex.set(h, newGroup); } } // Re-sort by latest DESC, cap size @@ -347,7 +350,7 @@ if (wsHandler) offWS(wsHandler); wsHandler = null; packets = []; - selectedId = null; + hashIndex = new Map(); selectedId = null; filtersBuilt = false; delete filters.node; expandedHashes = new Set(); @@ -385,6 +388,8 @@ const data = await api('/packets?' + params.toString()); packets = data.packets || []; + hashIndex = new Map(); + for (const p of packets) { if (p.hash) hashIndex.set(p.hash, p); } totalCount = data.total || packets.length; // When ungrouped, fetch observations for all multi-obs packets and flatten