No description
Find a file
Graham McIntire 63f25a9612
Some checks failed
Build prop-grid-rs / Test, build, push (push) Successful in 5m54s
Build and Push / Build and Push Docker Image (push) Failing after 4m44s
perf(grid-rs): dense grid, fused scoring pass, and columnar .pgrid profiles
Reworks the post-fetch half of the propagation pipeline. Fetch and GRIB2
decode were already cheap — measured against a live HRRR cycle, all 39
pressure messages decode via `wgrib2 -lola` in 0.29 s and the 31 MB
byte-range fetch takes ~3 s — so nothing here touches the decoder. All the
cost was downstream.

Also fixes a broken NOTIFY that made every chain step run up to 5 times.

pg_notify
  `NOTIFY propagation_ready, $1` is a Postgres syntax error: NOTIFY is a
  utility statement whose payload must be a literal, so a bind raises
  42601. It shared a transaction with the `status='done'` UPDATE, so every
  successful step rolled back, stayed 'running', and was requeued by
  reclaim_stale_running up to @max_reclaim_attempts times. Elixir's
  NotifyListener never fired either, so ScoreCache warm and the
  "propagation:updated" fan-out were dead.

FieldGrid
  A decoded grid was HashMap<(i32,i32), HashMap<Arc<str>, f32>> — a dense
  rectangular grid stored as ~95k nested hash maps, costing ~4.6M inserts
  on decode, ~3.7M on merge and ~14M lookups across three derivation
  passes. wgrib2 -lola already emits one dense row-major f32 block per
  message, so keep it: dense per-message planes, names hashed once per
  grid into plane ids, NaN as the missing sentinel. This is what forced
  PROP_GRID_RS_PARALLELISM=1 under a 3Gi limit.

Fused pass
  Three 95k-cell derivation passes plus 23 band-major scoring passes over
  a staged Vec<(f64,f64,Conditions,BandInvariants)> (~19MB re-streamed 23
  times) collapse into one pass: levels extracted once per cell, all 23
  bands scored while the cell is hot, scores accumulated cell-major so
  rayon chunks own disjoint slices. Scores land straight in the dense
  score-file body — no ScorePoint scatter.

.pgrid
  The profile artifact was an rmpv tree plus gzip -9, written 30x an hour,
  and ProfilesFile.read_point/3 gunzipped and unpacked the entire 95k-cell
  file to return one cell on every map click and Skew-T load. Replaced
  with a dense cell-major f32 record array carrying a self-describing
  field table. Elixir reads it via :file.pread; .mp.gz and .etf.gz remain
  readable so files written before this drain out of the 48h window.

  Measured on a full CONUS grid (95,073 cells x 48 planes x 23 bands):
    derive + score + build artifacts   0.022 s
    profile write   3.957 s -> 0.006 s (22.0 MB -> 22.4 MB on disk)
    single-cell read   whole-file decode -> 0.5 us
    23 score files     0.003 s

Also
  - hrrr_points: batched UNNEST upsert replacing one awaited INSERT per
    point. Keeps ON CONFLICT DO UPDATE — the PSKR sampler's two-pass loop
    depends on it.
  - fetcher: real semaphore capping in-flight ranges at
    MAX_PARALLEL_RANGES, which the comment claimed but the code did not do
    (it spawned all 27 while the connection pool was sized for 8).
  - metrics: per-stage histogram. Only chain-step and decode durations
    were instrumented, which is why the write cost stayed invisible.
  - profiles_file: parse_valid_time anchors on the known extension set, so
    sibling-suffixed names like <iso>.hrdps.prop no longer parse as
    <iso>.hrdps and vanish from prune and list operations.
  - PROP_GRID_RS_PARALLELISM 1 -> 3. Memory limit held at 3Gi until RSS is
    observed at the new parallelism.
  - cargo fmt over the crate; worker.rs, hrdps_fetcher.rs and nexrad.rs
    were already unformatted at HEAD and the pre-commit hook gates on it.

HRDPS still runs at 0.5 degrees. wgrib2 -lola scales linearly in output
points on rotated lat/lon (12.5 s wall, 202 s CPU for one message at
0.125 degrees) because it has no inverse projection for those grids; a raw
native dump is 0.32 s. The fix is decode-once plus a closed-form
rotated-pole index, left for a follow-up.
2026-08-01 08:23:36 -05:00
.forgejo/workflows ci: add postgres health-check options, remove fragile /dev/tcp wait 2026-07-28 08:31:28 -05:00
.github Add contact edit approval system with admin review queue 2026-04-11 16:15:49 -05:00
assets feat(weather): add duct cutoff band map layer 2026-05-15 19:51:24 -05:00
bin Fix livebook path resolution in bin/notebook 2026-04-07 11:15:49 -05:00
config feat: remove skippy HRRR proxy + disk cache, fetch directly from NOAA S3 2026-07-28 14:36:54 -05:00
docs feat: remove skippy HRRR proxy + disk cache, fetch directly from NOAA S3 2026-07-28 14:36:54 -05:00
k8s perf(grid-rs): dense grid, fused scoring pass, and columnar .pgrid profiles 2026-08-01 08:23:36 -05:00
lib perf(grid-rs): dense grid, fused scoring pass, and columnar .pgrid profiles 2026-08-01 08:23:36 -05:00
lib_ml fix: resolve all compiler warnings except framework-generated phoenix_component_verify 2026-05-29 10:18:52 -05:00
nix fix: point cargo pre-commit hooks at rust/prop_grid_rs/Cargo.toml 2026-07-20 19:52:18 -05:00
notebooks refactor: normalize pos1/pos2 JSONB key to 'lon' everywhere 2026-04-17 09:10:32 -05:00
priv fix: resolve 27 security, architecture, test, and performance audit findings 2026-07-27 18:19:37 -05:00
rel Add Erlang clustering via libcluster and expose LiveDashboard 2026-04-06 09:46:48 -05:00
rust/prop_grid_rs perf(grid-rs): dense grid, fused scoring pass, and columnar .pgrid profiles 2026-08-01 08:23:36 -05:00
scripts update ferqs 2026-07-20 19:55:52 -05:00
test perf(grid-rs): dense grid, fused scoring pass, and columnar .pgrid profiles 2026-08-01 08:23:36 -05:00
vendor chore(deps): bump vendored oban_web from 2.12.3 to 2.12.5 2026-07-30 08:30:38 -05:00
.credo.exs fix: resolve all 281 credo issues across source and test files 2026-07-29 09:04:21 -05:00
.dockerignore Optimize Dockerfile layer caching 2026-04-01 10:32:56 -05:00
.envrc Track .envrc with use flake, move secrets to .envrc.local 2026-07-20 18:35:13 -05:00
.formatter.exs initial 2026-03-28 11:28:47 -05:00
.gitignore Track .envrc with use flake, move secrets to .envrc.local 2026-07-20 18:35:13 -05:00
.tool-versions feat: add Nix flake dev environment with Erlang 29.0.3 + Elixir 1.20.2 2026-07-15 12:57:10 -05:00
AGENTS.md initial 2026-03-28 11:28:47 -05:00
algo.md feat(weather): /weather-ca endpoint shows HRDPS-only Canadian data 2026-04-30 12:08:48 -05:00
app.json Migrate healthchecks from CHECKS to app.json 2026-04-04 11:24:56 -05:00
bugs.md fix: 6 bugs from bugs.md — ADIF parser, Es MUF, enrichment reset, profile privacy, HRRR OOM risks 2026-05-12 09:37:09 -05:00
CLAUDE.md fix: resolve 27 security, architecture, test, and performance audit findings 2026-07-27 18:19:37 -05:00
Dockerfile fix: use apply/3 to avoid undefined-module warnings with Conditional ML module 2026-07-28 08:19:23 -05:00
Dockerfile.base fix: resolve 27 security, architecture, test, and performance audit findings 2026-07-27 18:19:37 -05:00
flake.lock feat: add Nix flake dev environment with Erlang 29.0.3 + Elixir 1.20.2 2026-07-15 12:57:10 -05:00
flake.nix feat: add Nix flake dev environment with Erlang 29.0.3 + Elixir 1.20.2 2026-07-15 12:57:10 -05:00
LICENSE Add GPLv3 license 2026-04-23 13:57:07 -05:00
Makefile chore: add AI-drift guardrails per Zornek article 2026-07-29 08:00:47 -05:00
mix.exs fix: resolve all 281 credo issues across source and test files 2026-07-29 09:04:21 -05:00
mix.lock fix: resolve all 281 credo issues across source and test files 2026-07-29 09:04:21 -05:00
nix.md feat: add Nix flake dev environment with Erlang 29.0.3 + Elixir 1.20.2 2026-07-15 12:57:10 -05:00
prediction.md HRRR forecast hours (f00-f18) with timeline map UI 2026-03-31 16:44:47 -05:00
README.md initial 2026-03-28 11:28:47 -05:00
shell.nix feat: add Nix flake dev environment with Erlang 29.0.3 + Elixir 1.20.2 2026-07-15 12:57:10 -05:00
tail_logs.sh Add type filter to backfill enqueue 2026-04-06 11:42:26 -05:00
updates.md Update seasonal scores from sounding data, document commercial link patterns 2026-04-07 11:45:44 -05:00

Microwaveprop

To start your Phoenix server:

  • Run mix setup to install and setup dependencies
  • Start Phoenix endpoint with mix phx.server or inside IEx with iex -S mix phx.server

Now you can visit localhost:4000 from your browser.

Ready to run in production? Please check our deployment guides.

Learn more