Status page NARR progress counted `hrrr_status = :unavailable` as the candidate set, which swept in ~13.6K post-2014 HRRR retry rows and showed "0 / 13,652". Candidate eligibility is qso_timestamp-based, not hrrr_status-based — switch both the numerator and denominator to `qso_timestamp < NarrClient.coverage_end()` so pre-2014 rows are counted whether their hrrr_status is :queued, :unavailable, or :complete. ContactWeatherEnqueueWorker: short-circuit hrrr_points_for_contact/1 for pre-coverage timestamps and mark the contact :unavailable when no HRRR jobs are built. Was producing a ping-pong where reconcile flipped pre-2014 :queued → :unavailable and the same cron run flipped it back to :queued from a rebuilt HRRR job that could never land data.
127 lines
4.2 KiB
Elixir
127 lines
4.2 KiB
Elixir
defmodule MicrowavepropWeb.StatusLiveTest do
|
|
use MicrowavepropWeb.ConnCase, async: false
|
|
|
|
import Microwaveprop.AccountsFixtures
|
|
import Phoenix.LiveViewTest
|
|
|
|
alias Microwaveprop.Cache
|
|
alias Microwaveprop.Radio.Contact
|
|
alias Microwaveprop.Repo
|
|
alias Microwaveprop.Weather.NarrProfile
|
|
|
|
setup %{conn: conn} do
|
|
Cache.invalidate({MicrowavepropWeb.StatusLive, :count_unprocessed})
|
|
Cache.invalidate({MicrowavepropWeb.StatusLive, :stats})
|
|
Cache.invalidate({MicrowavepropWeb.StatusLive, :db_stats})
|
|
|
|
user = user_fixture()
|
|
{:ok, admin} = user |> Ecto.Changeset.change(%{is_admin: true}) |> Repo.update()
|
|
conn = log_in_user(conn, admin)
|
|
{:ok, conn: conn}
|
|
end
|
|
|
|
defp create_narr_candidate do
|
|
{:ok, contact} =
|
|
%Contact{}
|
|
|> Contact.changeset(%{
|
|
station1: "W5TEST",
|
|
station2: "K5TEST",
|
|
qso_timestamp: ~U[2010-06-15 18:00:00Z],
|
|
mode: "CW",
|
|
band: Decimal.new("1296"),
|
|
grid1: "EM12",
|
|
grid2: "EM00",
|
|
pos1: %{"lat" => 33.0, "lon" => -97.0},
|
|
pos2: %{"lat" => 30.3, "lon" => -97.7},
|
|
distance_km: Decimal.new("300")
|
|
})
|
|
|> Ecto.Changeset.change(%{hrrr_status: :unavailable})
|
|
|> Repo.insert()
|
|
|
|
contact
|
|
end
|
|
|
|
# NARR fetches land in era5_profiles (table rename is a follow-up migration).
|
|
# The status UI labels this "NARR" now.
|
|
test "NARR progress bar numerator is actual profile matches not total-minus-candidates", %{conn: conn} do
|
|
create_narr_candidate()
|
|
|
|
# No NARR profile yet — candidates = 1, done = 0
|
|
{:ok, lv, _html} = live(conn, ~p"/status")
|
|
narr_row = lv |> element(~s|[data-progress-key="narr"]|) |> render()
|
|
assert narr_row =~ "NARR"
|
|
assert narr_row =~ "0 / 1"
|
|
|
|
# Insert a matching profile row — done should become 1
|
|
{:ok, _} =
|
|
Repo.insert(%NarrProfile{
|
|
valid_time: ~U[2010-06-15 18:00:00Z],
|
|
lat: 33.0,
|
|
lon: -97.0,
|
|
ducting_detected: false
|
|
})
|
|
|
|
Cache.invalidate({MicrowavepropWeb.StatusLive, :count_unprocessed})
|
|
|
|
{:ok, lv, _html} = live(conn, ~p"/status")
|
|
narr_row = lv |> element(~s|[data-progress-key="narr"]|) |> render()
|
|
assert narr_row =~ "1 / 1"
|
|
end
|
|
|
|
# NARR serves pre-2014 contacts only (NCEI archive ends 2014-10-02). A
|
|
# post-2014 contact with hrrr_status=:unavailable is a HRRR retry case,
|
|
# not a NARR candidate, and must not inflate the NARR denominator.
|
|
test "NARR progress excludes post-2014 hrrr-unavailable contacts", %{conn: conn} do
|
|
# pre-2014 candidate (counts toward NARR)
|
|
create_narr_candidate()
|
|
|
|
# post-2014 hrrr-unavailable contact (does NOT count toward NARR)
|
|
{:ok, _} =
|
|
%Contact{}
|
|
|> Contact.changeset(%{
|
|
station1: "W5POST",
|
|
station2: "K5POST",
|
|
qso_timestamp: ~U[2020-06-15 18:00:00Z],
|
|
mode: "CW",
|
|
band: Decimal.new("1296"),
|
|
grid1: "EM12",
|
|
grid2: "EM00",
|
|
pos1: %{"lat" => 33.0, "lon" => -97.0},
|
|
pos2: %{"lat" => 30.3, "lon" => -97.7},
|
|
distance_km: Decimal.new("300")
|
|
})
|
|
|> Ecto.Changeset.change(%{hrrr_status: :unavailable})
|
|
|> Repo.insert()
|
|
|
|
{:ok, lv, _html} = live(conn, ~p"/status")
|
|
narr_row = lv |> element(~s|[data-progress-key="narr"]|) |> render()
|
|
assert narr_row =~ "0 / 1"
|
|
end
|
|
|
|
# NARR eligibility is defined by qso_timestamp, not hrrr_status. A
|
|
# pre-2014 contact whose hrrr_status is still :queued (the ping-pong
|
|
# window before reconcile flips it) must still be counted — otherwise
|
|
# the denominator misses rows for several cron cycles after submission.
|
|
test "NARR candidates include pre-2014 contacts regardless of hrrr_status", %{conn: conn} do
|
|
{:ok, _} =
|
|
%Contact{}
|
|
|> Contact.changeset(%{
|
|
station1: "W5QUE",
|
|
station2: "K5QUE",
|
|
qso_timestamp: ~U[2010-06-15 18:00:00Z],
|
|
mode: "CW",
|
|
band: Decimal.new("1296"),
|
|
grid1: "EM12",
|
|
grid2: "EM00",
|
|
pos1: %{"lat" => 33.0, "lon" => -97.0},
|
|
pos2: %{"lat" => 30.3, "lon" => -97.7},
|
|
distance_km: Decimal.new("300")
|
|
})
|
|
|> Ecto.Changeset.change(%{hrrr_status: :queued})
|
|
|> Repo.insert()
|
|
|
|
{:ok, lv, _html} = live(conn, ~p"/status")
|
|
narr_row = lv |> element(~s|[data-progress-key="narr"]|) |> render()
|
|
assert narr_row =~ "0 / 1"
|
|
end
|
|
end
|