Commit graph

128 commits

Author SHA1 Message Date
e99e585b66 Add type filter to backfill enqueue
Backfill dashboard now has checkboxes to select which enrichment types
to process (HRRR, Weather, Terrain, IEMRE). Prevents weather jobs from
flooding the queue when only HRRR needs work.
2026-04-06 11:42:26 -05:00
091d469c6a Enable OS and Ecto data in LiveDashboard, fix progress bars
- Add ecto_psql_extras for PostgreSQL insights in dashboard
- Add os_mon for OS metrics (CPU, memory, disk)
- Fix progress bars using percentage instead of raw large numbers
2026-04-06 09:56:08 -05:00
2de94e2318 Add Erlang clustering via libcluster and expose LiveDashboard
- libcluster with Kubernetes IP strategy for pod discovery
- RBAC for pod list/get, POD_IP from downward API, shared cookie
- LiveDashboard at /dashboard for all environments
2026-04-06 09:46:48 -05:00
5bee273442
Combine active jobs and completed cards on backfill dashboard 2026-04-06 09:03:44 -05:00
bb32e12c6a
Fix backfill progress layout - wider card, no text wrapping 2026-04-06 09:02:32 -05:00
95d7fc0c39
Show per-type enrichment progress bars on backfill dashboard 2026-04-06 08:59:38 -05:00
f4d3773e2b
Fix backfill progress to use exact counts instead of pg_stat estimates 2026-04-06 08:54:30 -05:00
0b68cb2d29
Disable propagation grid worker and add maintenance banner to map 2026-04-05 17:08:40 -05:00
d1b1b4cc7e
Show flag emoji on contacts list for flagged_invalid contacts 2026-04-05 09:15:02 -05:00
16883591b4
Database performance fixes and async backfill enqueue
- Fix score_pressure crash on nil pressure_mb (coastal HRRR points)
- Set 10-min timeout on grid score upsert transaction (was :infinity)
- Single DELETE for prune_old_scores instead of N queries in a loop
- Remove dead load_hrrr_refractivity that loaded 95k rows into nil map
- Pass selected_time to point_detail to skip latest_valid_time sub-query
- Batch station existence checks (1 query per path point, not per station)
- Batch solar index upserts via insert_all in chunks of 500
- Batch backfill_distances via single UPDATE FROM VALUES statement
- Add is_grid_point boolean + partial index to hrrr_profiles (replaces
  non-sargable modular arithmetic filter on every weather map query)
- Add partial index on contacts(qso_timestamp) WHERE pos1 IS NOT NULL
- Move backfill enqueue to Oban worker so UI returns immediately
2026-04-04 19:19:18 -05:00
a209fc65ae
Restrict enrichment enqueue to T-Mobile CGNAT subnet (172.56.0.0/13)
Store remote_ip in session, check subnet in LiveView mount before
enqueuing weather/HRRR/terrain/solar enrichment jobs.
2026-04-04 18:55:42 -05:00
383c18e50a
Show IEMRE gridded reanalysis data on contact detail page 2026-04-04 11:35:30 -05:00
da490f7c59
Add tooltip to enrichment badge showing per-type status 2026-04-04 11:26:35 -05:00
6d2f1fb4c3
Fix swapped Submitted/Enriched column headers 2026-04-04 11:22:06 -05:00
72b272cf5c
Add enrichment status badge column to contacts table 2026-04-04 11:15:18 -05:00
915e8bdccf
Add UTC labels to Timestamp and Added column headers 2026-04-04 11:11:01 -05:00
95a2afaa01
Add inserted_at column to contacts table 2026-04-04 10:51:39 -05:00
e107706915
Show dead tuple counts on backfill dashboard, fix table visibility during vacuum
Removed n_live_tup > 0 filter that hid tables when pg_stats reports 0 rows
during VACUUM. Added dead tuple column with warning highlight to monitor
vacuum progress. Also includes Styler reformatting and unused dep cleanup.
2026-04-04 10:45:06 -05:00
4759c65809
Support two-callsign search on contacts page to find contacts between a pair 2026-04-04 09:29:32 -05:00
f411045242
Add layer descriptions to weather map control panel 2026-04-03 17:21:02 -05:00
08844d3515
Add grouped upper-air and ducting layer buttons to weather map 2026-04-03 16:53:22 -05:00
109558f7cc
Add weather map link to propagation map sidebar 2026-04-03 15:16:05 -05:00
1796ee4cb7
Add WeatherMapLive LiveView with layer pill buttons 2026-04-03 15:11:55 -05:00
1c7c980cf4
Debounce backfill dashboard updates to once per second 2026-04-03 10:52:24 -05:00
78bc577824
Show 'processing' instead of '1 job in queue' 2026-04-02 16:46:32 -05:00
f9c6e3730a
Allow retry of unavailable enrichment on page load 2026-04-02 16:46:12 -05:00
a8920e9480
Fix position computation, grid truncation, and status resets
- Truncate odd-length grids to nearest valid even length (FN03c → FN03)
- Handle lng/lon key inconsistency in haversine distance calculation
- Reset unavailable statuses to pending when positions are computed
- Rename backfill queue column to "Pending"
2026-04-02 16:31:34 -05:00
33171ab32e
Replace polling with Postgres LISTEN/NOTIFY for live updates
- Database triggers on contacts and oban_jobs fire pg_notify on
  status/state changes
- RepoListener GenServer subscribes via Postgrex.Notifications and
  broadcasts to PubSub
- Backfill dashboard subscribes to PubSub instead of 2-second polling
- Eliminates periodic SELECT queries, updates arrive instantly
2026-04-02 16:26:22 -05:00
12d7dbf7ea
Fix phantom queued status when Oban unique constraint rejects job 2026-04-02 16:22:06 -05:00
d36256e730
Show queue position on all loading spinners, fix solar backfill
- Unified queue_info helper shows "(N jobs in queue)" on all spinners
- Solar index auto-enqueues when missing on contact page
- Freshness monitor disabled in dev
- Fix test stubs for solar client
2026-04-02 16:17:31 -05:00
0e089e8493
Auto-fetch solar index data on contact page when missing
- SolarIndexWorker accepts date arg for specific date fetch
- Contact show page enqueues solar fetch when data missing
- PubSub broadcast on solar data arrival, live-updates page
- Spinner shown while fetching
2026-04-02 16:07:38 -05:00
9fe53b4e7b
Fix terrain enqueue: check actual data not just status flag 2026-04-02 16:04:38 -05:00
7d13bf20ea
Fix raw SQL references to renamed contacts table 2026-04-02 15:55:15 -05:00
da75977a55
Rename qsos table to contacts, qso_id to contact_id
- Migration renames table, column, all indexes, and FK constraints
- Contact schema now references "contacts" table
- TerrainProfile foreign key renamed from qso_id to contact_id
- All code and tests updated to use contact_id
2026-04-02 15:52:19 -05:00
ae0e667cab
Fix backfill LiveStash recovery: always set all required assigns 2026-04-02 15:37:54 -05:00
d275e9e7c4
fix enrichment 2026-04-02 15:30:41 -05:00
15a09f0d7b
Fix enrichment: check actual data presence, not just status flag 2026-04-02 15:27:18 -05:00
f897a9a321
Re-enqueue enrichment jobs when status is queued but data missing
Previously, if a job was cancelled or lost while status was :queued,
viewing the contact detail page would not re-enqueue. Now HRRR,
weather/soundings, and terrain all re-enqueue when :queued with no
data, relying on Oban uniqueness for deduplication.
2026-04-02 15:07:49 -05:00
bb1c46fd57
Fix backfill page 500 by using pg_stat estimates instead of count(*)
The 6 sequential count(*) queries on large tables were timing out
at 15s when concurrent HRRR batch inserts held locks. Reuse the
n_live_tup estimates already fetched from pg_stat_user_tables.
2026-04-02 14:55:53 -05:00
66de041886
Show HRRR queue position on contact detail page
When HRRR data is loading, display how many jobs are ahead
in the queue so users can estimate wait time.
2026-04-02 14:42:45 -05:00
1c2879c466
Fix ambiguous column reference in backfill DB stats query 2026-04-02 13:29:15 -05:00
faa23a9693
Add Data Sources section to contact detail page
Shows provenance of all data used in the analysis:
- HRRR: path profile count, pressure levels, valid time, grid point
- Elevation: sample count, path distance, source (SRTM), duct layers
- Terrain: sample count, verdict, max elevation, diffraction loss
- Surface observations: station count and time range
- Soundings: profile count, stations, levels, ducting detection
- Solar indices: SFI, SSN, Ap
2026-04-02 13:28:58 -05:00
2452f1f397
Add detailed database stats to backfill dashboard
- Enrichment status breakdown per type (HRRR/Weather/Terrain/IEMRE)
  with color-coded status counts (complete/pending/queued/failed)
- Database overview: total DB size, HRRR profiles, observations,
  soundings with per-contact averages
- Table sizes: rows and disk size per table, sorted by size
- All stats auto-refresh every 2 seconds
2026-04-02 13:24:43 -05:00
59665a5009
Add LiveStash to backfill page, recover limit on reconnect 2026-04-02 13:13:23 -05:00
c1da0f20b1
Add LiveStash for state recovery across reconnects
- Installed live_stash ~> 0.1 with browser memory adapter
- Map page: recovers selected_band and selected_time on reconnect
- Submit page: recovers active_tab (single/csv) on reconnect
- JS params initialized with initLiveStash wrapper
2026-04-02 13:12:17 -05:00
2f65c4648c
Add /health endpoint and CHECKS file for zero-downtime deploys 2026-04-02 13:01:42 -05:00
20ed47397b
Improve map page mobile usability
Collapsible control panel with hamburger toggle, detail panel as
bottom sheet, compact legend moved to top-right, and scaled timeline
buttons for narrow viewports.
2026-04-02 12:59:55 -05:00
1da1cbed43
Fix nil access bugs found in security/bug audit
- TerrainProfileWorker: guard pos1/pos2 nil before accessing lat/lon,
  mark unavailable if missing instead of crashing
- Propagation analysis: guard pos1 nil in compute_factors
- contact_path_points: return [] instead of [{nil, nil}] on missing coords
- JS elevation hook: null check canvas before getContext
2026-04-02 12:38:49 -05:00
2b14e836f1
Fix CSV parsing and page number input validation
- RFC 4180 CSV parser: handles quoted fields with commas and escaped
  quotes ("Smith, John" no longer breaks parsing)
- Safe page number parsing: non-numeric input defaults to page 1
  instead of raising ArgumentError
2026-04-02 12:32:59 -05:00
79af4e4959
Ensure positions computed from grids before any enrichment
- Radio.ensure_positions!/1 computes pos1/pos2/distance from grids
- Called in contact show page mount and enqueue_for_contact
- Migration backfills positions for existing contacts missing them
- Migration corrects enrichment statuses based on actual data presence
- Backfill dashboard includes contacts with grids but no positions
2026-04-02 12:28:48 -05:00