The hourly cron now only seeds grid_tasks. The chain step, native-duct
merge, NEXRAD merge, commercial-link merge, scoring, ProfilesFile
write, and band-score writes all moved to rust/prop_grid_rs.
Elixir changes:
- GridTaskEnqueuer.seed_with_analysis/1: inserts 1 kind='analysis' row
(f00) + 18 kind='forecast' rows (f01..f18).
- PropagationGridWorker: stripped from 423 LOC to a thin seeder.
perform(%{}) → GridTaskEnqueuer.seed_with_analysis.
Deleted: process_forecast_hour, merge_native_duct_data,
merge_nexrad_data, merge_commercial_link_data, compute_scores_*,
persist_profiles, record_run_timing (Rust emits spans to Prometheus
instead), apply_nexrad_observations, apply_duct_grid, timed helpers.
Test rewritten for the new shape: 0 Oban fan-out jobs, 19 grid_tasks
rows with the expected kind distribution.
HrrrNativeClient and NexradClient remain — they have other callers
(HrrrNativeGridWorker for per-QSO duct batch; NexradWorker and
CommonVolumeRadarWorker for per-contact radar). Only f00's direct
use moved.
88 lines
3.1 KiB
Elixir
88 lines
3.1 KiB
Elixir
defmodule Microwaveprop.Workers.PropagationGridWorkerTest do
|
|
@moduledoc """
|
|
Tests the Phase-3-cutover seeder behaviour.
|
|
|
|
Elixir no longer runs the chain step; the hourly cron fires
|
|
`perform(%Oban.Job{args: %{}})` with empty args and the worker
|
|
inserts 19 grid_tasks rows (1 analysis f00 + 18 forecast f01..f18)
|
|
for the Rust `prop-grid-rs` worker to drain. Rust owns HRRR fetch,
|
|
wgrib2 decode, native duct, NEXRAD, commercial, scoring, and both
|
|
the ProfilesFile and band score-file writes from here on out.
|
|
"""
|
|
use Microwaveprop.DataCase, async: false
|
|
use Oban.Testing, repo: Microwaveprop.Repo
|
|
|
|
alias Microwaveprop.Workers.PropagationGridWorker
|
|
alias Microwaveprop.Workers.PropagationPruneWorker
|
|
|
|
describe "queue priority" do
|
|
test "PropagationGridWorker runs at the highest priority on :propagation" do
|
|
assert PropagationGridWorker.__opts__()[:priority] == 0
|
|
end
|
|
|
|
test "PropagationPruneWorker yields to the grid chain" do
|
|
assert PropagationPruneWorker.__opts__()[:priority] > 0
|
|
end
|
|
end
|
|
|
|
describe "perform/1 — chain seeding (empty args)" do
|
|
test "inserts 1 analysis + 18 forecast grid_tasks rows; no Oban fan-out" do
|
|
Oban.Testing.with_testing_mode(:manual, fn ->
|
|
import Ecto.Query
|
|
|
|
assert :ok = PropagationGridWorker.perform(%Oban.Job{args: %{}})
|
|
|
|
# No chain-step Oban jobs fan out anymore — the entire chain
|
|
# lives in grid_tasks from the Rust worker's perspective.
|
|
jobs = all_enqueued(worker: PropagationGridWorker)
|
|
assert jobs == []
|
|
|
|
{_count, [first_task]} =
|
|
"grid_tasks"
|
|
|> Microwaveprop.Repo.insert_all(
|
|
[],
|
|
returning: [:run_time, :kind, :forecast_hour]
|
|
)
|
|
|> case do
|
|
# When the worker seeded a run, the table has 19 fresh rows.
|
|
# Pull the analysis row so the test can derive run_time for
|
|
# the subsequent query.
|
|
_ ->
|
|
from(t in "grid_tasks",
|
|
where: t.kind == "analysis",
|
|
order_by: [desc: t.inserted_at],
|
|
limit: 1,
|
|
select: %{run_time: t.run_time, forecast_hour: t.forecast_hour, kind: t.kind}
|
|
)
|
|
|> Microwaveprop.Repo.all()
|
|
|> case do
|
|
[row] -> {1, [row]}
|
|
_ -> {0, [%{run_time: nil, forecast_hour: nil, kind: nil}]}
|
|
end
|
|
end
|
|
|
|
assert first_task.kind == "analysis"
|
|
assert first_task.forecast_hour == 0
|
|
run_time = first_task.run_time
|
|
assert run_time.minute == 0
|
|
assert run_time.second == 0
|
|
|
|
rows =
|
|
Microwaveprop.Repo.all(
|
|
from t in "grid_tasks",
|
|
where: t.run_time == ^run_time,
|
|
select: %{fh: t.forecast_hour, kind: t.kind},
|
|
order_by: [t.kind, t.forecast_hour]
|
|
)
|
|
|
|
kinds = rows |> Enum.map(& &1.kind) |> Enum.frequencies()
|
|
assert kinds == %{"analysis" => 1, "forecast" => 18}
|
|
|
|
forecast_fhs =
|
|
rows |> Enum.filter(&(&1.kind == "forecast")) |> Enum.map(& &1.fh) |> Enum.sort()
|
|
|
|
assert forecast_fhs == Enum.to_list(1..18)
|
|
end)
|
|
end
|
|
end
|
|
end
|