Dedup relay copies per observer and increase DB connection limit

Drop duplicate MQTT packets when the same packet hash arrives at the
same observer with the same hop count within 120s. Increase TimescaleDB
max_connections to 300 to prevent connection exhaustion on startup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ben
2026-03-08 12:26:09 +00:00
co-authored by Claude Opus 4.6
parent 2de39a871a
commit b9a231ef36
2 changed files with 32 additions and 0 deletions
+31
View File
@@ -101,6 +101,33 @@ function isEmptyPacketEnvelope(json: Record<string, unknown>, rawHex: string, pa
&& (payloadLen ?? 0) <= 0;
}
/**
* Per-observer packet dedup — prevents relay copies of the same packet from being
* ingested multiple times when they arrive at the same observer with the same hop count.
* Keyed by "packetHash:observerKey:hopCount". Entries expire after 120 seconds.
*/
const seenPackets = new Map<string, number>();
const SEEN_PACKETS_MAX = 50_000;
const SEEN_PACKETS_TTL_MS = 120_000;
function isDuplicatePacket(packetHash: string, observerKey: string, hopCount: number | undefined): boolean {
const now = Date.now();
// Periodic cleanup
if (seenPackets.size > SEEN_PACKETS_MAX / 2) {
for (const [k, ts] of seenPackets) {
if (now - ts > SEEN_PACKETS_TTL_MS) seenPackets.delete(k);
}
}
const key = `${packetHash}:${observerKey}:${hopCount ?? '?'}`;
if (seenPackets.has(key)) return true;
if (seenPackets.size >= SEEN_PACKETS_MAX) {
const oldest = seenPackets.keys().next().value;
if (oldest !== undefined) seenPackets.delete(oldest);
}
seenPackets.set(key, now);
return false;
}
/**
* Dedup map for advert counts — prevents relay copies of the same advert packet
* from incrementing the count multiple times. Keyed by decoded message hash.
@@ -424,6 +451,10 @@ async function handleMessage(topic: string, rawPayload: Buffer): Promise<void> {
const finalHash = decodedHash ?? (json['hash'] as string | undefined) ?? crypto.randomUUID();
if (isDuplicatePacket(finalHash, observerKey, decodedHops)) {
return;
}
void upsertNode(observerKey, { iata, network });
emitNode(observerKey, { network, observerId: observerKey });
+1
View File
@@ -2,6 +2,7 @@ services:
timescaledb:
image: timescale/timescaledb:latest-pg16
restart: unless-stopped
command: ["postgres", "-c", "max_connections=300"]
environment:
POSTGRES_DB: ${POSTGRES_DB:-meshcore}
POSTGRES_USER: ${POSTGRES_USER:-meshcore}