Drop 10 dead parser-compat columns (srccallsign, dstcallsign,
origpacket, body, header, alive, posambiguity, symboltable,
symbolcode, messaging) and move 14 display-only columns into a
single `data` JSONB column (PHG, telemetry, radiorange,
information_field, format, posresolution, position_ambiguity,
luminosity, rain_midnight).
Reduces row width from ~70 to ~48 columns. Table is ephemeral
so migration uses DROP/recreate. Also fixes snow_24h -> snow bug
in weather check query and adds null byte stripping for JSONB
string sanitization.
Extract device attribute addition into helper function to reduce
cyclomatic complexity from 10 to 9:
- callsign_json.ex: Extract add_device_attributes/2 helper
Moves device.model, device.vendor, device.contact, and device.class
attribute additions into separate function
This reduces complexity by isolating the && operators in a dedicated
helper function.
Fixes 1 Credo cyclomatic complexity issue (10 remaining).
- 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>
- Add support for station-specific URLs (e.g., /w5isp) as path parameters
- Always display the most recent packet for tracked stations, regardless of trail/historical duration
- Fetch and store tracked callsign's latest packet on mount
- Update packet filtering to preserve tracked callsign's packet even if outside time threshold
- Keep tracked callsign's latest packet updated with real-time arrivals
- Display tracked callsign's packet immediately when map loads
- Remove obsolete RedirectController in favor of direct LiveView routing
This ensures users viewing a specific station always see its most recent position,
even if it falls outside the selected historical timeframe.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add SKIP_DB_CREATE env var to skip database creation when using PgBouncer
- Fix redis_children() to return proper child specs
- Implement zero-downtime graceful shutdown without user notifications
- Add health check plug for Kubernetes probes
- Remove user-facing shutdown notifications for seamless deployments
Co-Authored-By: Claude <noreply@anthropic.com>
Both /status and /status.json endpoints now show cluster-wide APRS-IS
connection status instead of just local node status.
Features:
- get_cluster_aprs_status() checks all nodes in cluster via RPC
- Returns status from any connected node (usually the leader)
- Shows cluster info: total nodes, connected nodes, leader node
- Graceful fallback to local status in non-clustered mode
- Enhanced status page UI with cluster information display
This ensures status pages accurately reflect the true APRS-IS
connection state across the entire cluster.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit introduces several major performance improvements and adds
robust error handling for malformed HTTP requests:
Performance Optimizations:
- Add database migration with BRIN indexes for time-series data and partial
indexes for recent queries, significantly improving query performance
- Create global StreamingPacketsPubSub system for real-time packet distribution
with geographic bounds filtering using ETS for fast lookups
- Refactor PacketConsumer to use Stream module for memory-efficient processing,
preventing memory accumulation during batch operations
- Implement dedicated BroadcastTaskSupervisor pool for async broadcast operations,
preventing GenServer blocking on I/O
- Increase database connection pool from 25 to 45 (production) and 15 to 30 (dev)
for better concurrency support
Error Handling:
- Add SentryFilter to prevent Bandit.HTTPError from missing Host headers from
cluttering Sentry (common with bots/scanners)
- Configure custom 400 Bad Request error handling
- Filter out common bot/scanner paths from error reporting
All changes include comprehensive test coverage following TDD practices.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>