fix(weather-ca): drop the 1h freshness cutoff so HRDPS data renders

The 1-hour valid_time filter inherited from /weather is wrong for
HRDPS: the model publishes 4x/day with 3-4h publication latency and
the chain step adds ~13 min on top, so the freshest data on disk is
routinely 4-6h old. With the 1h cutoff in place, /weather-ca's
timeline was empty whenever there wasn't an active chain step running,
which left the JS hook with nothing to fetch. The sidebar already
shows the selected valid_time prominently — users can see for
themselves how stale the data is and don't need the page to hide it.
This commit is contained in:
Graham McIntire 2026-04-30 12:24:34 -05:00
parent fdadba52b8
commit 4901c83916
No known key found for this signature in database
GPG key ID: F4ABF488E6029E59
2 changed files with 39 additions and 7 deletions

View file

@ -104,13 +104,13 @@ defmodule MicrowavepropWeb.WeatherCaMapLive do
Enum.min_by(valid_times, fn vt -> abs(DateTime.diff(vt, now, :second)) end)
end
# Drop valid_times older than one hour. HRDPS cycles run 4×/day and
# the chain seeder writes one row per hour, so the on-disk set can
# span many old hours; the user wants "now", not yesterday.
defp recent_valid_times(valid_times) do
cutoff = DateTime.add(DateTime.utc_now(), -3600, :second)
Enum.filter(valid_times, fn vt -> DateTime.compare(vt, cutoff) != :lt end)
end
# Don't filter by recency. HRDPS publishes 4×/day with a 3-4h
# publication latency and our chain step adds ~13 min on top, so the
# freshest valid_time on disk is routinely 4-6h old. /weather's 1h
# cutoff would leave /weather-ca empty most of the time. The sidebar
# shows the selected valid_time in big letters — users can see for
# themselves how stale the data is.
defp recent_valid_times(valid_times), do: valid_times
defp build_path(socket, overrides \\ []) do
layer = Keyword.get(overrides, :layer, socket.assigns.selected_layer)

View file

@ -6,6 +6,7 @@ defmodule MicrowavepropWeb.WeatherCaMapLiveTest do
alias Microwaveprop.Propagation.ProfilesFile
alias Microwaveprop.Weather.GridCache
alias Microwaveprop.Weather.ScalarFile
setup do
GridCache.clear()
@ -54,4 +55,35 @@ defmodule MicrowavepropWeb.WeatherCaMapLiveTest do
assert_patch(lv, "/weather-ca?layer=pwat&lat=55.0&lon=-100.0&zoom=4")
end
test "shows HRDPS valid_times even when several hours old (no 1h cutoff)", %{conn: conn} do
# HRDPS publishes 4x/day with ~3-4h latency, plus our chain step
# takes ~13 min. The 1-hour cutoff /weather uses would routinely
# leave /weather-ca empty between fresh chain steps. Hand-write a
# 4-hour-old HRDPS chunk and confirm it lands in the timeline.
now =
DateTime.utc_now()
|> DateTime.truncate(:second)
|> Map.put(:minute, 0)
|> Map.put(:second, 0)
stale_t = DateTime.add(now, -4 * 3600, :second)
hrdps_dir = ScalarFile.dir_for_hrdps(stale_t)
File.mkdir_p!(hrdps_dir)
payload =
Msgpax.pack!(
[%{"lat" => 53.0, "lon" => -60.0, "valid_time" => DateTime.to_iso8601(stale_t), "temperature" => 8.0}],
iodata: false
)
File.write!(Path.join(hrdps_dir, "10_-12.mp.gz"), :zlib.gzip(payload))
on_exit(fn -> File.rm_rf!(hrdps_dir) end)
{:ok, _lv, html} = live(conn, ~p"/weather-ca")
iso = DateTime.to_iso8601(stale_t)
assert html =~ iso, "4-hour-old HRDPS valid_time should appear in /weather-ca timeline"
end
end