prop/lib/microwaveprop
Graham McIntire 9f583a16bf
perf(weather/scalar_file): single MessagePack format for both Elixir and Rust
Move ScalarFile from a dual-writer dual-format setup (ETF on the Elixir
side, materialized via NotifyListener; nothing on the Rust side) to a
single chunked-MessagePack format that both languages produce and
consume.

Elixir side:

- ScalarFile now writes gzipped MessagePack `.mp.gz` per chunk via
  Msgpax. Reader decodes with Msgpax + zlib. Atom keys are stripped to
  strings on encode and re-atomized via a whitelist on read so callers
  see the same shape regardless of which side wrote the bytes.
- DateTime values round-trip through ISO8601 strings.
- New cross-language wire-format test that decodes a hand-rolled
  payload mirroring exactly what `rmp_serde::to_vec_named` emits, so a
  format regression on either side fails the suite.

Rust side:

- New `prop_grid_rs::weather_scalar_file` module:
  - 1:1 port of `Microwaveprop.Weather.WeatherLayers.derive/1` plus
    the surface fields `Weather.build_grid_cache_row/4` adds on top
    (lapse rate, mid lapse rate, inversion strength + base, 850/700 mb
    interpolation, surface RH, surface refractivity, ducting flag).
  - `write_atomic` chunks rows into 5°×5° buckets, writes one
    `<lat_band>_<lon_band>.mp.gz` per chunk via tmp + rename, drops
    pre-existing chunks first to keep writes canonical.
  - 5 unit tests covering surface-only rows, upper-air derivation,
    write/read round-trip, chunk band boundaries, and the
    out-of-physical-range surface-temp filter.
- Pipeline integration: both `run_chain_step` (f01..f18) and the f00
  analysis path now build `Vec<ScalarRow>` in the same merged-cell
  pass that builds `CellEntry` and `Conditions`, then fire a parallel
  `spawn_blocking` write that overlaps with scoring. Awaiting the
  scalar future after the score-band writes keeps the failure-surface
  symmetric with the existing profile_future.

Result: every new forecast hour lands with the scalar artifact already
on disk, so /weather reads never fall through to ProfilesFile decode +
per-cell SoundingParams + WeatherLayers derivation. The Elixir-side
`NotifyListener.handle_propagation_ready/1` materialization remains as
an idempotent safety net for hours that pre-date this commit.
2026-04-29 08:26:28 -05:00
..
accounts feat(accounts): derive 10-char home_grid from explicit lat/lon 2026-04-25 17:04:45 -05:00
backtest fix(dialyzer): clear 125+ warnings under strict flags 2026-04-21 10:30:06 -05:00
beacon_monitors Add dialyzer specs and types across the codebase 2026-04-12 08:55:04 -05:00
beacons Short-circuit RangeEstimate below 5.76 GHz to stop browser lockup 2026-04-14 16:56:24 -05:00
buildings fix(buildings): use explicit step in descending range in encode_quadkey 2026-04-26 10:54:44 -05:00
callsign_location Drop gridmap.org dependency, resolve callsigns locally 2026-04-12 17:43:29 -05:00
canopy feat(rover): add canopy clutter penalty + Canopy.BulkFetch downloader 2026-04-26 12:57:50 -05:00
commercial test: push line coverage from 71.7% → 78.67% 2026-04-23 18:43:18 -05:00
ionosphere fix(ionosphere): disable TLS verify for GIRO to unbreak ionosonde fetch 2026-04-22 09:49:03 -05:00
prom_ex perf(prop): cap ScoreCache LRU + drop eager warmers to fix hot-pod OOMs 2026-04-24 18:49:36 -05:00
propagation perf(weather): serve /weather from chunked scalar artifacts 2026-04-28 17:15:36 -05:00
qrz feat(telemetry): broaden Instrument span coverage 2026-04-18 17:25:33 -05:00
radio feat(import): strip non-printables from CSV/ADIF uploads 2026-04-26 15:34:46 -05:00
rover refactor: deduplicate helpers and simplify Scorer 2026-04-28 14:14:34 -05:00
space_weather fix(ingest): dedupe ASOS duplicates + shrink SWPC decode errors 2026-04-21 16:39:17 -05:00
terrain refactor: deduplicate helpers and simplify Scorer 2026-04-28 14:14:34 -05:00
weather perf(weather/scalar_file): single MessagePack format for both Elixir and Rust 2026-04-29 08:26:28 -05:00
workers fix: log swallowed async task exits in GEFS scoring and HRRR range fetch 2026-04-27 14:22:10 -05:00
accounts.ex feat(accounts): auto-prefill home QTH from QRZ on register + backfill on boot 2026-04-25 17:03:01 -05:00
application.ex fix: log every silent error path so failures surface in k8s logs 2026-04-27 14:31:30 -05:00
backtest.ex chore(specs): add @spec to public API in accounts/release/backtest 2026-04-21 13:32:42 -05:00
beacon_monitors.ex Add dialyzer specs and types across the codebase 2026-04-12 08:55:04 -05:00
beacons.ex fix(dialyzer): actually fix LiveTable warnings instead of hiding them 2026-04-21 12:58:10 -05:00
cache.ex fix(cache): add periodic TTL sweeper to bound ETS growth 2026-04-21 13:19:53 -05:00
callsign_location.ex Drop gridmap.org dependency, resolve callsigns locally 2026-04-12 17:43:29 -05:00
canopy.ex feat(canopy): add tree-canopy height layer for path obstruction analysis 2026-04-26 12:51:48 -05:00
commercial.ex fix: April 2026 codebase review — address 13 bugs across propagation chain 2026-04-25 10:52:51 -05:00
format.ex refactor(format): consolidate number/bytes formatters + handle flaky IEM transports 2026-04-21 17:09:41 -05:00
geo.ex refactor: deduplicate helpers and simplify Scorer 2026-04-28 14:14:34 -05:00
geocoder.ex feat(telemetry): broaden Instrument span coverage 2026-04-18 17:25:33 -05:00
instrument.ex feat(telemetry): wide instrumentation + bump hrrr to 2 per pod 2026-04-18 16:33:34 -05:00
ionosphere.ex refactor: deduplicate helpers and simplify Scorer 2026-04-28 14:14:34 -05:00
mailer.ex Send mail as prop@w5isp.com with reply-to graham@mcintire.me 2026-04-12 14:00:38 -05:00
markdown.ex Add dialyzer specs and types across the codebase 2026-04-12 08:55:04 -05:00
moon.ex feat(eme): add /eme Earth-Moon-Earth calculator 2026-04-23 16:18:20 -05:00
oban_error_reporter.ex feat(observability): attach Oban exception telemetry tap 2026-04-21 14:13:53 -05:00
prom_ex.ex fix: stabilize flaky tests + silence PromEx Oban poller in test 2026-04-21 13:49:07 -05:00
propagation.ex fix(path): handle ProfilesFile cell shape correctly + log async exits 2026-04-25 15:57:20 -05:00
qrz.ex Drop gridmap.org dependency, resolve callsigns locally 2026-04-12 17:43:29 -05:00
radio.ex refactor: deduplicate helpers and simplify Scorer 2026-04-28 14:14:34 -05:00
release.ex chore(specs): add @spec to public API in accounts/release/backtest 2026-04-21 13:32:42 -05:00
repo.ex initial 2026-03-28 11:28:47 -05:00
repo_listener.ex chore(specs): add @spec to public API in accounts/release/backtest 2026-04-21 13:32:42 -05:00
rover.ex feat(rover-locations): add /rover-locations page with CRUD 2026-04-26 13:08:27 -05:00
space_weather.ex refactor(db): use explicit on_conflict set clauses over :replace_all_except 2026-04-21 14:22:15 -05:00
terrain.ex Add dialyzer specs and types across the codebase 2026-04-12 08:55:04 -05:00
weather.ex perf(weather): serve /weather from chunked scalar artifacts 2026-04-28 17:15:36 -05:00