Commit graph

23 commits

Author SHA1 Message Date
b86153cd27
Fix all mix credo --strict warnings (188 → 0)
- Replace apply/2 with direct fully-qualified calls in movement_test
- Fix assert_receive timeouts < 1000ms across 8 test files
- Move nested import statements to module-level scope
- Fix tests with no assertions and add missing doctest
- Replace weak type assertions with specific value checks
- Fix conditional assertions and length/1 expensive patterns
- Disable inappropriate Jump.CredoChecks.AvoidSocketAssignsInTest
- Fix tests not calling application code with credo:disable
- Add various credo:disable comments for legitimate patterns
2026-06-12 16:27:20 -05:00
f225f57044
perf(packets): keyset-based pagination for recent-packet queries
get_recent_packets/1 and get_recent_packets_for_map/1 now accept a
:cursor option (%{received_at: DateTime, id: uuid}) instead of :offset
for deep paging. On the 100M-row partitioned packets table, offset
scanning was linear in page depth; keyset is constant.

Ordering tightened to (received_at DESC, id DESC) so the cursor is
stable across ties. idx_packets_received_desc still covers the lookup;
a dedicated (received_at DESC, id DESC) index isn't worth its size
given microsecond timestamp granularity.

historical_loader migrated from batch_offset*batch_size scheduling to
a sequential cursor chain. The old loader fanned out N Process.send_after
batches up-front which could arrive out-of-order; the cursor version
waits for batch N before scheduling N+1, and also short-circuits the
remaining schedule when an under-full batch signals exhaustion.

mobile_channel load_historical_packets dropped its meaningless
`offset: 0`; callsign history already lacked offset.

No LiveView or WebSocket payload shapes changed. offset: 0 (or omitted)
still behaves as first page; non-zero offsets are silently ignored.
2026-04-21 10:15:04 -05:00
b8a9b8a465
chore(dialyzer): enable stricter flags and fix 97 resulting findings
Turned on :error_handling, :underspecs, and :unmatched_returns in
mix.exs dialyzer config. The 97 warnings this surfaced were fixed in
place rather than suppressed:

- unmatched_return (79): explicit discard with `_ = ...` for
  fire-and-forget side effects (Process.cancel_timer, :ets.new,
  send/2), and pattern-matched `:ok = ...` for control-plane
  Phoenix.PubSub subscribe/unsubscribe/broadcast calls so a future
  return-shape change fails loud.

- contract_supertype (18): tightened @spec arg and return types on
  data_builder, historical_loader, url_params, packet_utils,
  encoding_utils, aprs_symbol, weather_controller, packet_replay to
  match each function's actual success typing.

No behavioural change. mix compile clean, 1008 tests pass, dialyzer
count is now 0.
2026-04-21 10:07:01 -05:00
d22fc7c661
Fix dialyzer type errors in coordinate validation
- Remove redundant nil check for callsign (spec guarantees String.t())
- Simplify coordinate validation by removing faulty infinity checks
- Remove unreachable catch-all clause in has_weather_packets?

Floats cannot equal atoms :infinity or :neg_infinity in Elixir.
Range checks already ensure finite values, making explicit infinity
checks unnecessary. Reduces dialyzer errors from 40 to 34.
2026-02-20 18:17:59 -06:00
8755bba9f0
Optimize historical packet loading by selecting only needed columns
Historical map loading previously fetched all 73 columns (SELECT *) from
the packets table (~2068 bytes/row). Added get_recent_packets_for_map/1
with select_map_fields/1 that fetches only the 22 columns needed for map
rendering (~200 bytes/row), yielding a ~3x query speedup.

Also removes unused all_packets tracking from PacketProcessor and
simplifies visible_packets cleanup in Index.
2026-02-20 07:41:14 -06:00
7b488e9fd7
Fix code review findings batch 2: dead code, encoding, correctness
- Delete dead modules: Archiver, PacketPipelineSetup, SystemMonitor
- Encoding: fast-path for clean ASCII, fix latin1 C1 control chars (128-159)
- SpatialPubSub: fix date line grid cell wrapping
- QueryBuilder: use indexed has_weather column instead of 10-way OR
- PacketProcessor/HistoricalLoader: wire up heat map via DisplayManager
- MapLive: add PacketBatcher crash recovery with Process.monitor
- MapLive: fix time display re-render by touching assign
- DeviceCache: remove unreachable outer try/rescue
- Remove dead stubs: RateLimiterWrapper count/reset, DeviceIdentification enqueue_refresh_job
- Simplify Application.pubsub_config/0
- Add tests for SpatialPubSub, PacketBatcher, encoding, weather_only
2026-02-20 07:29:27 -06:00
509f271eac
Improve packet pipeline reliability, security, and cleanup efficiency
- Fix XSS vulnerability in buildPopupContent fallback (escape callsign/comment)
- Add batch insert retry with individual fallback in PacketConsumer
- Add APRS-IS login response validation (logresp dispatch handler)
- Fix stale generation check bypass in HistoricalLoader
- Replace two-step SELECT+DELETE cleanup with single CTE-based batch DELETE
- Change default packet retention from 365 to 7 days
- Delete MapHelpers (100% duplicate of CoordinateUtils + BoundsUtils)
- Delete AprsIsConnection (dead code, second unused APRS-IS connection)
- Fix InfoMap hook memory leak (store/cancel setTimeout ref)
- Extract singleton loadMapBundle with callback queue in app.js
- Extract @heat_map_max_zoom constant in DisplayManager
- Add telemetry to cleanup worker and PacketProducer buffer overflow
- Track PacketProducer buffer_size as integer for O(1) length checks
- Remove duplicate bounds functions from index.ex
2026-02-19 14:11:48 -06:00
6653678860
Reduce cyclomatic complexity in high-complexity functions
Extract helper functions to reduce complexity in functions with
complexity 10-15:

- packet.ex: Extract add_symbol_data/2
  Moves symbol data extraction into separate function
  Reduces complexity from 10 to 9

- mobile_channel.ex: Extract bounds validation helpers
  Creates all_numeric?/4, valid_latitudes?/2, valid_longitudes?/2
  Moves complex boolean conditions into readable helper functions
  Reduces complexity from 15 to within limits

- historical_loader.ex: Extract packet_has_valid_coordinates?/1
  Moves coordinate validation logic with multiple conditions
  Reduces complexity from 15 to within limits

Fixes 3 more Credo cyclomatic complexity issues.
2026-02-09 13:15:17 -06:00
41000e3482
Fix remaining nesting depth issues
Extracts nested logic into helper functions to comply with Credo
requirements (max nesting depth 2):

- data_builder.ex: Extract historical packet data building
  (build_historical_packet_data/2)
  Reduces depth 3 -> depth 2

- streaming_packets_pubsub.ex: Extract subscriber filtering and messaging
  (send_to_matching_subscribers/5)
  Removes conditional check by sending cleanup message unconditionally
  (GenServer handles empty list gracefully)
  Reduces depth 3 -> depth 2

- historical_loader.ex: Extract RF path station loading logic
  (maybe_load_rf_path_stations/3)
  Reduces depth 3 -> depth 2

- packet_processor.ex: Extract marker popup logic
  (send_marker_with_popup_check/2)
  Reduces depth 3 -> depth 2

Fixes all 4 remaining Credo nesting depth issues.
All nesting depth issues now resolved (0 remaining).
2026-02-09 12:37:38 -06:00
0f8b60c2f4
Reduce cyclomatic complexity in historical packet loader
Extract packet query logic into helper functions:
- query_historical_packets: Main query orchestration with error handling
- build_query_params: Build query parameters with callsign filtering
- maybe_include_latest_packet: Include latest packet for tracked callsigns

This breaks down the complex do_load_historical_batch function.

Co-Authored-By: Graham <noreply@anthropic.com>
2026-02-09 12:06:58 -06:00
dc0bc7bbdf
Fix credo warnings and start on design suggestions
Warnings fixed (13 issues):
- Replace expensive length/1 checks with empty list comparisons
- Remove redundant n == n comparison in is_finite guards
- Use proper type notation in @spec instead of struct literal

Design suggestions (3/13 files):
- Add aliases for nested modules in historical_loader, page_controller, mobile_channel

Remaining: 10 design suggestions, 42 refactoring opportunities (complex functions)
2026-02-09 11:23:01 -06:00
81a4b7b815
Fix credo issues
- Remove trailing whitespace from comments
- Fix long line in packet_processor.ex
- Rename is_leader? to leader? following Elixir conventions
2026-02-09 11:17:56 -06:00
cc4578653f
cleanup and remove redis 2025-10-22 16:19:17 -05:00
5e3f0bc5cf
fix coord bug 2025-10-19 09:06:58 -05:00
9b207e0d67
updates with parser updates 2025-08-03 09:19:31 -05:00
90d7f58a53
fix: Always show most recent position for tracked callsigns
Ensure that when viewing a specific callsign (e.g., /w5isp), the most
recent position packet is always displayed, regardless of how old it is
or what historical time period is selected.

The fix ensures that during historical loading, if we're tracking a
specific callsign and it's the first batch, we always include the
callsign's most recent packet even if it falls outside the selected
historical time filter (1h, 3h, 6h, etc.).

This resolves the issue where callsigns with very old last positions
would not be visible when viewing their specific page.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-30 14:52:53 -05:00
9f52f8cb49
fix: Resolve infinite "loading historical data" issue
Fix the issue where the historical data loading indicator would get stuck
indefinitely when no packets are found for a callsign or time period.

Changes:
- Handle empty packet results by properly updating loading state
- Add failsafe timeout (30s) to prevent infinite loading states
- Add debug logging to help identify when no packets are found
- Ensure loading progress is updated even when batches return no data

This fixes the issue where viewing callsigns with no recent data would
show "loading historical data" forever.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-30 14:49:40 -05:00
41c148650d
refactor: Remove CachedQueries and rename optimized functions
- Remove all CachedQueries usage throughout the codebase
- Replace with direct Packets module calls
- Delete CachedQueries module entirely
- Rename get_recent_packets_optimized to get_recent_packets
- Add has_weather_packets? function to Packets module
- Fix duplicate function definitions
- Update all test references to use new function names

This simplifies the codebase by removing the caching layer and
eliminates the database ownership errors in tests.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-30 13:17:56 -05:00
d5781f2581
Fix comprehensive crash prevention and add missing RF path station markers
This commit addresses two major areas:

1. Crash Prevention & Error Handling:
   - Added error handling to all database queries to prevent crashes
   - Implemented circuit breaker pattern for APRS-IS connection
   - Added timeouts to all Redis operations (5 second timeout)
   - Fixed unsafe pattern matches that could cause MatchError crashes
   - Added try/rescue blocks around background tasks
   - Improved socket operation error handling with proper cleanup
   - Enhanced packet cleanup worker with comprehensive error handling

2. RF Path Station Markers:
   - Fixed issue where digipeater/iGate icons weren't shown when searching for callsigns
   - Now loads and displays position markers for all stations in the RF path
   - Extracts RF path stations from tracked callsign packets
   - Fetches latest position for each digipeater/iGate
   - Properly displays complete RF path visualization with station positions

Technical details:
- Added Process.alive? checks before sending messages
- Fixed resource cleanup in terminate functions
- Added proper error handling to File.read operations
- Implemented safe wrapper for ShutdownHandler health checks
- All changes ensure the app continues running even when errors occur

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-28 11:56:00 -05:00
92585ae34f
Fix race condition when zooming map quickly
- Increase debounce time from 300ms to 400ms for bounds updates
- Cancel in-progress historical loading when new bounds are scheduled
- Add stale update detection to skip outdated bounds updates
- Clear timer reference and pending bounds when processing updates
- Add debug logging for cancelled loads and stale updates

This prevents overlapping historical data loads during rapid zoom
changes, eliminating duplicate packets and improving performance.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-18 12:27:46 -05:00
b4fcd4382e
Fix missing socket return in handle_pending_bounds
The function was sending a message but not returning the socket,
causing an ArgumentError when the result was passed to assign/3.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-15 11:14:48 -05:00
3730b8c848
performance improvements 2025-07-14 16:35:58 -05:00
e6ccb9662b
major refactor for cleanup 2025-07-14 12:06:10 -05:00