- Switch PacketProducer buffer from list to :queue for O(1) overflow handling - Add cached leadership check via :persistent_term to eliminate GenServer.call bottleneck in packet distribution hot path - Simplify packets_live coordinate extraction from 70 lines of nested conditionals to helper functions (extract_coordinate/2, format_coordinate/1) - Remove debug logging from hot paths (packets.ex queries, PacketDistributor, app.js console.logs) - Remove sobelow dependency (false positives blocking commits) - Add 25 new tests for PacketProducer, coordinate helpers, and cached leadership
4 KiB
4 KiB
TODO
APRS-IS Connection
- Consolidate
AprsIsConnectionandAprsme.Isinto a single implementation — removedAprsIsConnection(was dead code opening a second useless APRS-IS connection) - Validate APRS-IS server login response — added
dispatch("# logresp " <> rest)clause that logs unverified vs accepted login - Add APRS-IS login response validation — server sends
# logrespline indicating accept/reject - [~] Cap circuit breaker half-open recovery — assessed: the passive transition is the standard pattern;
get_statechecks elapsed time before everycall, so recovery is always timely. No change needed.
Packet Intake Pipeline
- Add retry logic for batch insert failures in
PacketConsumer.process_chunk/1— wrappedRepo.insert_allin try/rescue with fallback to individual inserts viainsert_individually/1 - Improve
PacketProducerbuffer drop logging — trackbuffer_sizeas integer (O(1)), added telemetry for buffer overflow events - Switch
PacketProducerbuffer from list to:queue— O(1) amortized enqueue/dequeue instead of O(n)Enum.takeon overflow; also fixes LIFO→FIFO dispatch order - Cluster packet distribution race — replaced
GenServer.callleadership check with:persistent_termcached read vialeader_cached?/0; eliminates per-packet serialization through LeaderElection GenServer - Add backpressure mechanism — no global rate limiting if APRS-IS sends burst traffic; only defense is fixed-size buffer with silent drops
Front-End Display
- Fix XSS vulnerability in PopupComponent fallback — added
escapeHtml()tomap_helpers.ts, applied to callsign and comment inbuildPopupContentinmap.ts - Simplify coordinate extraction in
packets_live/index.html.heex— extractedextract_coordinate/2andformat_coordinate/1helpers intoPacketsLive.Index; template went from 70 lines of nested conditionals to 6 lines - Fix memory leak in InfoMap hook — stored
setTimeoutref inthis.resizeTimer, cancel indestroyed() - Fix Leaflet bundle loading race — extracted singleton
loadMapBundle()with callback queue inapp.js - Add loading indicator for real-time bounds updates — only
@historical_loadingtriggers spinner, not bounds filtering - Fix stale generation check bypass in
historical_loader.ex:100-108— split into two function clauses: nil generation always loads, integer generation checks staleness - Consolidate coordinate/bounds validation — deleted
MapHelpersmodule (was 100% duplicate ofCoordinateUtils+BoundsUtils); updated all callers inindex.ex,data_builder.ex,mobile_channel.ex - Extract hard-coded zoom threshold (8) for heat map to a constant — extracted
@heat_map_max_zoom 8indisplay_manager.ex - Remove debug logging from hot paths — removed
Logger.debugcalls frompackets.exquery path,PacketDistributor, andconsole.logstatements fromapp.js
Packet Purging
- Shorter default retention — changed from 365 days to 7 days (configurable via
PACKET_RETENTION_DAYSenv var) - Improve cleanup efficiency — replaced two-step SELECT IDs + DELETE by IDs with single-query CTE-based batch DELETE; eliminates extra round-trip per batch
- Add cleanup telemetry — added
:telemetry.executetocleanup_packets_older_than_batched/1 - [~] Partial index for cleanup queries — assessed: existing
packets_received_at_idxB-tree is already optimal forWHERE received_at < $1 LIMIT $2; partial index with dynamic cutoff adds no benefit - [~] ETS PacketStore TTL mismatch — assessed: the 2-hour ETS TTL is intentional for LiveView memory efficiency; DB retention is for historical data. Different purposes, not a bug.
- Consider PostgreSQL table partitioning — partition packets by time range (daily/weekly) for instant
DROP PARTITIONcleanup instead of batch DELETEs; requires one-time migration but not worth the complexity unless cleanup exceeds 5-minute time limit regularly