Commit graph

407 commits

Author SHA1 Message Date
989d310447
fix(grid-rs): fall back to NOAA S3 when the LAN HRRR proxy is down
Root cause of the blank /map analysis breakdown: the skippy.w5isp.com
caching proxy was unreachable from the cluster, so every f00 analysis
step failed at the idx fetch and Rust never wrote a ProfilesFile. The
/map point-detail panel silently degraded to empty factors because
no profile ever lands on `/data/scores/profiles/`.

HrrrClient now takes an optional fallback base. When the primary base
exhausts its retries (5× exponential backoff), fetches retry once
against the fallback — defaulted to the NOAA S3 public bucket. Forecast,
analysis, and native-duct paths all go through the same
fetch_blob_with_fallback helper so a proxy outage degrades to direct
S3 instead of stalling.

Moved the native-URL builder out of native_duct into fetcher so the
single helper can build both primary and fallback URLs for the native
hybrid-sigma product.
2026-04-21 15:54:02 -05:00
FluxCD
02bf34db9e chore: update prop image to git.mcintire.me/graham/prop:main-1776798788-48d30f1 [skip ci] 2026-04-21 19:16:25 +00:00
540750b3d3
fix(observability): re-enable OTLP export for Elixir
Set OTEL_EXPORTER_OTLP_ENDPOINT on the prop deployment to the cluster
Collector so Phoenix/Bandit/Oban spans export and link up with
downstream prop-grid-rs / prop-hrrr-point-rs traces in Tempo. Without
this the Elixir app fell back to traces_exporter :none and the Rust
worker spans had no parent, leaving the trace graph disconnected.

The stale comment referenced opentelemetry_ecto as the reason export
was off, but that package was never added to mix.exs (only
opentelemetry_phoenix / _bandit / _oban are listed), so the
span-flood concern no longer applies.
2026-04-21 13:26:27 -05:00
FluxCD
e9b804f628 chore: update prop image to git.mcintire.me/graham/prop:main-1776786279-38ef716 [skip ci] 2026-04-21 15:47:20 +00:00
FluxCD
6c977e250d chore: update prop image to git.mcintire.me/graham/prop:main-1776785420-d61fbd3 [skip ci] 2026-04-21 15:34:05 +00:00
FluxCD
2f5b37f7c5 chore: update prop image to git.mcintire.me/graham/prop:main-1776783205-7b78a25 [skip ci] 2026-04-21 14:55:46 +00:00
FluxCD
e5991d324a chore: update prop image to git.mcintire.me/graham/prop:main-1776782574-71c134d [skip ci] 2026-04-21 14:46:43 +00:00
FluxCD
61da51c03f chore: update prop image to git.mcintire.me/graham/prop:main-1776781734-f4f44b5 [skip ci] 2026-04-21 14:31:32 +00:00
FluxCD
360a0e32c1 chore: update prop image to git.mcintire.me/graham/prop:main-1776781470-33be6d0 [skip ci] 2026-04-21 14:27:27 +00:00
FluxCD
9ced0eab87 chore: update prop image to git.mcintire.me/graham/prop:main-1776780470-fbbb8b2 [skip ci] 2026-04-21 14:16:16 +00:00
FluxCD
cd2962687a chore: update prop image to git.mcintire.me/graham/prop:main-1776777603-cc9220b [skip ci] 2026-04-21 13:23:57 +00:00
FluxCD
cb9d9fb30b chore: update prop image to git.mcintire.me/graham/prop:main-1776752742-c96bdca [skip ci] 2026-04-21 06:35:16 +00:00
FluxCD
e3d7f5b2c2 chore: update prop image to git.mcintire.me/graham/prop:main-1776722189-30525a1 [skip ci] 2026-04-20 21:59:07 +00:00
FluxCD
ff241afa6e chore: update prop image to git.mcintire.me/graham/prop:main-1776721927-aebf391 [skip ci] 2026-04-20 21:55:01 +00:00
FluxCD
9815bd691e chore: update prop image to git.mcintire.me/graham/prop:main-1776721607-e641fce [skip ci] 2026-04-20 21:49:58 +00:00
FluxCD
796fb22d4b chore: update prop image to git.mcintire.me/graham/prop:main-1776721085-ee732d0 [skip ci] 2026-04-20 21:45:54 +00:00
FluxCD
00101ca928 chore: update prop image to git.mcintire.me/graham/prop:main-1776720629-bd3b114 [skip ci] 2026-04-20 21:34:50 +00:00
FluxCD
77b54a1642 chore: update prop image to git.mcintire.me/graham/prop:main-1776719536-9bf9634 [skip ci] 2026-04-20 21:14:47 +00:00
FluxCD
6463b7261f chore: update prop image to git.mcintire.me/graham/prop:main-1776715484-c78cb97 [skip ci] 2026-04-20 20:07:30 +00:00
FluxCD
c10cf176e7 chore: update prop image to git.mcintire.me/graham/prop:main-1776714901-52ce44d [skip ci] 2026-04-20 19:57:23 +00:00
FluxCD
7244a59a21 chore: update prop image to git.mcintire.me/graham/prop:main-1776712929-ddedd24 [skip ci] 2026-04-20 19:25:01 +00:00
FluxCD
444de00ef7 chore: update prop image to git.mcintire.me/graham/prop:main-1776712357-a7bea4a [skip ci] 2026-04-20 19:14:53 +00:00
FluxCD
26640b1204 chore: update prop image to git.mcintire.me/graham/prop:main-1776711181-608fd32 [skip ci] 2026-04-20 18:55:45 +00:00
FluxCD
0c1d90ef58 chore: update prop image to git.mcintire.me/graham/prop:main-1776710724-f3fab30 [skip ci] 2026-04-20 18:47:39 +00:00
FluxCD
818b270a0a chore: update prop image to git.mcintire.me/graham/prop:main-1776710473-1a1ba46 [skip ci] 2026-04-20 18:44:39 +00:00
1a1ba460e4
fix(otel): drop opentelemetry_ecto + disable OTLP on Elixir pods
Ecto auto-instrumentation created one span per query, so Oban jobs
running thousands of DB ops produced traces with 8k+ child spans.
Tempo's compactor couldn't ingest them — it stalled long enough to
miss heartbeats, got auto-forgotten from the ring, and crash-looped.
The Elixir grpcbox exporter then blew up trying to reconnect.

Stops the cascade: OTLP endpoint removed from prop and prop-backfill
Deployments, opentelemetry_ecto removed from deps, Phoenix/Oban/Bandit
auto-instrumentation retained. Rust workers still export to Tempo.
2026-04-20 13:41:01 -05:00
FluxCD
5f4c02fb46 chore: update prop image to git.mcintire.me/graham/prop-grid-rs:main-1776709289-ed2563f [skip ci] 2026-04-20 18:39:39 +00:00
FluxCD
67c6d74fcf chore: update prop image to git.mcintire.me/graham/prop:main-1776709289-ed2563f [skip ci] 2026-04-20 18:34:26 +00:00
efa3cc804d
perf(rust): disk-backed HRRR idx cache + scale workers off talos5
Shared NFS idx cache at /data/hrrr_idx lets all prop-grid-rs and
hrrr-point-rs replicas deduplicate redundant NOAA S3 idx fetches.
Opt-in via HRRR_IDX_CACHE_DIR; falls back to in-memory-only when unset.

Also scales prop-grid-rs to 3 replicas (no talos5 pinning),
hrrr-point-rs to 2 replicas, and drops hot pod replicas 4→3 so the
physical-host anti-affinity still fits with talos5 cordoned off for
Postgres.
2026-04-20 13:18:38 -05:00
FluxCD
e2a2ad42fd chore: update prop image to git.mcintire.me/graham/prop:main-1776705188-b6b5945 [skip ci] 2026-04-20 17:17:04 +00:00
FluxCD
456f674d92 chore: update prop image to git.mcintire.me/graham/prop:main-1776704597-55251df [skip ci] 2026-04-20 17:11:01 +00:00
FluxCD
648bccb108 chore: update prop image to git.mcintire.me/graham/prop-grid-rs:main-1776704403-65a1b1e [skip ci] 2026-04-20 17:03:55 +00:00
55251df8a0
feat(elixir): OpenTelemetry trace export to cluster OTel Collector
Adds the OTel deps (opentelemetry + exporter + phoenix / ecto / oban /
bandit auto-instrumentation helpers) and attaches them in
Application.start/2 so the existing Phoenix, Ecto, Oban, and Bandit
telemetry events flow as OTLP spans without any call-site changes.

Exporter config is gated on OTEL_EXPORTER_OTLP_ENDPOINT in
config/runtime.exs — set in the k8s manifests to the cluster
collector (otel-collector.observability.svc.cluster.local:4317).
When unset we switch traces_exporter to :none so nothing is shipped;
dev/test stays quiet.

Resource attributes tag spans with service.name=microwaveprop and
service.namespace=prop, matching the Rust workers' attribute shape
so Tempo can group the full hourly chain across both languages.

Both the main prop deployment and the backfill deployment get the
env; backfill is still a full BEAM node running enrichment workers,
so its Oban/Ecto spans are worth seeing too.
2026-04-20 12:02:15 -05:00
65a1b1edb3
feat(rust): OTLP trace export to cluster OTel Collector
New telemetry module wires tracing-subscriber to both a local JSON
fmt layer (keeps kubectl-logs output identical) and an
OpenTelemetry OTLP/gRPC exporter, activated only when
OTEL_EXPORTER_OTLP_ENDPOINT is set. The returned TelemetryGuard
holds the SdkTracerProvider until process shutdown so queued spans
flush before exit.

Both bin targets (worker, hrrr_point_worker) now call
telemetry::init(service_name) at startup; service_name becomes the
OTel service.name attribute so Tempo groups spans per binary.

Tracing instrumentation on the three main work units:
- pipeline::run_chain_step (forecast f01..f18)
- pipeline::run_analysis_step (analysis f00)
- hrrr_points::process_batch (per-QSO point drain)

k8s manifests set OTEL_EXPORTER_OTLP_ENDPOINT to the cluster
collector at otel-collector.observability.svc.cluster.local:4317.
Backend wiring lives in the vntx-infra repo.
2026-04-20 11:59:49 -05:00
FluxCD
a52d2e2b93 chore: update prop image to git.mcintire.me/graham/prop:main-1776694898-8089a16 [skip ci] 2026-04-20 14:26:18 +00:00
FluxCD
cfcc0a412f chore: update prop image to git.mcintire.me/graham/prop-grid-rs:main-1776694896-8089a16 [skip ci] 2026-04-20 14:25:16 +00:00
a1d2e9f94a
fix(hrrr-points): bind jsonb[] correctly, warn on empty fetch, 2 Gi limit
Three fixes after hrrr-point-rs restarts on the first live drain:

1. Type mismatch (hard error): the `profile` column on `hrrr_profiles`
   is `jsonb[]` (one element per pressure level), but the Rust worker
   was binding a single jsonb array-of-objects cast as `::jsonb`. Every
   insert failed with `column "profile" is of type jsonb[] but
   expression is of type jsonb`. Switched to
   `Vec<sqlx::types::Json<Value>>`, dropped the explicit `::jsonb`
   cast, and enabled sqlx's `json` feature so the encoder maps the
   array into `_jsonb` correctly.

2. Silent zero-inserts: four consecutive 2019-09-22 batches completed
   with `profiles_inserted: 0` and no diagnostic. Most likely the
   upstream archive doesn't keep cycles that old, but without a log
   it looks identical to a snap-mismatch bug. Added a WARN when both
   surface and pressure grids come back empty so fetch-miss vs.
   projection-miss is distinguishable.

3. OOMKilled: the pod took four OOM restarts in ten minutes at 1 Gi.
   A single CONUS decode holds the ~40 MB blob, the ~200 MB wgrib2
   working set, AND the full 92k-cell merged map until all requested
   points drain. 1 Gi has no headroom. Bumped to 2 Gi, matching the
   rest of the per-container budgets in this namespace.
2026-04-20 09:18:52 -05:00
FluxCD
48da629147 chore: update prop image to git.mcintire.me/graham/prop:main-1776693990-68910f4 [skip ci] 2026-04-20 14:09:13 +00:00
68910f4d72
k8s(grid-rs): drop parallelism to 1 after 3 Gi still OOMs at 2
Two concurrent forecast tasks plus the NFS score-file write cache (23
files x ~2 MB) plus the analysis step's wgrib2 peak repeatedly crossed
the 3 Gi cgroup limit. Single-lane parallelism per pod keeps steady RSS
under 2 Gi; with 2 replicas that still gives 2 concurrent tasks
cluster-wide.

PROP_GRID_RS_PG_CONNS follows the parallelism+2 formula, dropping from
4 to 3.
2026-04-20 09:06:17 -05:00
FluxCD
1135e4b156 chore: update prop image to git.mcintire.me/graham/prop-grid-rs:main-1776693159-141956b [skip ci] 2026-04-20 14:04:09 +00:00
FluxCD
f05f80ef91 chore: update prop image to git.mcintire.me/graham/prop:main-1776693158-141956b [skip ci] 2026-04-20 13:54:56 +00:00
FluxCD
f671114105 chore: update prop image to git.mcintire.me/graham/prop:main-1776692049-1cbc3e5 [skip ci] 2026-04-20 13:36:51 +00:00
FluxCD
ab653f37ef chore: update prop image to git.mcintire.me/graham/prop:main-1776691261-a3cfff3 [skip ci] 2026-04-20 13:24:35 +00:00
a3cfff3048
fix(grid-rs): bump memory 2→3 Gi, parallelism 3→2, re-trigger Rust CI
Two bugs surfacing 13 h after Stream A cutover:

1. prop-grid-rs pods OOMKilled 16–18× overnight on the analysis step.
   f00's native-level GRIB2 (~530 MB + wgrib2 working set) runs on top
   of 2 concurrent forecast tasks, briefly reaching ~2 Gi. 2 Gi limit
   was too tight — 3 Gi plus parallelism 3→2 gives the analysis step
   room without eliminating forecast-lane headroom.

2. hrrr-point-rs pod is CrashLoopBackOff because its container is
   running image main-1776640915-65f7963 (pre-Stream-C) which doesn't
   contain the hrrr_point_worker binary. The grid-rs CI run for
   commit 4fefb81 failed and no newer image got published. Touch the
   Dockerfile to re-trigger the workflow so flux picks up a new tag
   with both binaries. No functional Dockerfile change, just a
   docstring update so the path-filter kicks.

Forecast + analysis both claim per FOR UPDATE SKIP LOCKED, so
reducing per-pod parallelism doesn't break the chain — the two
replicas cover 4 slots cluster-wide, which still drains f01..f18 in
~5 min.
2026-04-20 08:20:48 -05:00
FluxCD
2421bf562a chore: update prop image to git.mcintire.me/graham/prop:main-1776641293-4fefb81 [skip ci] 2026-04-19 23:31:18 +00:00
FluxCD
f481f11df1 chore: update prop image to git.mcintire.me/graham/prop-grid-rs:main-1776640915-65f7963 [skip ci] 2026-04-19 23:28:35 +00:00
4fefb81c24
feat(hrrr-point-rs): Rust binary for per-QSO HRRR enrichment
Phase 3 Stream C Rust side. Completes the HrrrFetchWorker port.

Pipeline:
- db::claim_next_hrrr_task — FOR UPDATE SKIP LOCKED on hrrr_fetch_tasks,
  newest valid_time first. Accepts the points JSONB directly.
- hrrr_points::process_batch — fetch surface + pressure GRIB2 once
  per task (tokio::try_join), decode via the existing wgrib2 plumbing,
  then for each requested point pull the cell and UPSERT INTO
  hrrr_profiles (conflict on lat/lon/valid_time).
- db::complete_hrrr_task / fail_hrrr_task — status transitions; Elixir
  backfill re-enqueues failed rows on next /30-min scan.

Shipping pieces:
- new bin src/bin/hrrr_point_worker.rs
- new module src/hrrr_points.rs (process_batch, upsert_profile)
- new Cargo [[bin]] entry; Dockerfile builds both binaries in one stage
  and ships them in the runtime image so a single CI pipeline covers
  the whole cluster
- k8s/deployment-hrrr-point-rs.yaml (1 replica, 1 Gi limit, anti-affinity
  against prop-grid-rs so chain + point work don't fight for wgrib2
  slots). Uses the same image; command: override picks the right binary.
- kustomization.yaml: include the new deployment so flux applies it
- deployment-grid-rs.yaml: bump readiness initialDelaySeconds 3→15 +
  failureThreshold 3→6 so a slow DB connect during startup can't race
  the first probe

119 Rust tests green.
2026-04-19 18:28:00 -05:00
FluxCD
586222be63 chore: update prop image to git.mcintire.me/graham/prop:main-1776640955-7416583 [skip ci] 2026-04-19 23:27:05 +00:00
FluxCD
ab784daff7 chore: update prop image to git.mcintire.me/graham/prop-grid-rs:main-1776640915-65f7963 [skip ci] 2026-04-19 23:23:00 +00:00
FluxCD
03b8c4d5d4 chore: update prop image to git.mcintire.me/graham/prop:main-1776640446-cd7f2fc [skip ci] 2026-04-19 23:16:58 +00:00