prop/test/microwaveprop/workers/propagation_grid_worker_test.exs
Graham McIntire 504f5147f6
fix(propagation): hourly grid chain preempts MRMS/prune backlog
The :propagation queue (2 slots) is shared by PropagationGridWorker,
MrmsFetchWorker (every 2 min), and PropagationPruneWorker (every
15 min). Oban dispatches priority-then-FIFO, so a post-deploy
MRMS/prune backlog could delay the hourly chain step until the
siblings drained.

Set PropagationGridWorker priority: 0 explicitly and drop the two
siblings to priority: 5 so new chain steps always jump ahead.
Backfill workers live on separate queues (:hrrr, :weather, :terrain,
:iemre, :narr, :radar, :mechanism) and already don't interact with
the predictor.
2026-04-19 08:42:22 -05:00

71 lines
2.7 KiB
Elixir
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

defmodule Microwaveprop.Workers.PropagationGridWorkerTest do
@moduledoc """
Tests the chain-orchestration behavior of PropagationGridWorker.
The worker processes forecast hours f00f18 across the CONUS grid,
but a single full sweep takes ~2 hours of wall time — longer than a
typical pod restart window. To survive deploys, the worker processes
ONE forecast hour per `perform/1` call and enqueues the next hour as
a fresh Oban job. The tests here cover the dispatch + chain logic
without mocking the full HRRR / scoring stack.
"""
use Microwaveprop.DataCase, async: false
use Oban.Testing, repo: Microwaveprop.Repo
alias Microwaveprop.Workers.MrmsFetchWorker
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 "MrmsFetchWorker and PropagationPruneWorker yield to the grid chain" do
# Same :propagation queue — must be lower priority so hourly chain
# steps jump ahead of a MRMS or pruner backlog.
assert MrmsFetchWorker.__opts__()[:priority] > 0
assert PropagationPruneWorker.__opts__()[:priority] > 0
end
end
describe "perform/1 — chain seeding (empty args)" do
test "enqueues a single fh=0 chain step with a normalized run_time" do
Oban.Testing.with_testing_mode(:manual, fn ->
assert :ok = PropagationGridWorker.perform(%Oban.Job{args: %{}})
[child] = all_enqueued(worker: PropagationGridWorker)
assert child.args["forecast_hour"] == 0
assert is_binary(child.args["run_time"])
{:ok, run_time, _} = DateTime.from_iso8601(child.args["run_time"])
assert run_time.minute == 0
assert run_time.second == 0
assert DateTime.before?(run_time, DateTime.utc_now())
end)
end
end
describe "enqueue_next_step/2" do
test "enqueues fh+1 when fh < max" do
run_time = ~U[2026-04-14 16:00:00Z]
Oban.Testing.with_testing_mode(:manual, fn ->
assert {:ok, _} = PropagationGridWorker.enqueue_next_step(run_time, 0)
[child] = all_enqueued(worker: PropagationGridWorker)
assert child.args["forecast_hour"] == 1
assert child.args["run_time"] == DateTime.to_iso8601(run_time)
end)
end
test "does not enqueue anything after the final forecast hour" do
run_time = ~U[2026-04-14 16:00:00Z]
Oban.Testing.with_testing_mode(:manual, fn ->
assert :final = PropagationGridWorker.enqueue_next_step(run_time, 18)
assert [] = all_enqueued(worker: PropagationGridWorker)
end)
end
end
end