HTTP 404 means the HRRR data doesn't exist on NOAA S3 (pre-2014
dates, etc.) and will never succeed. Return {:cancel, reason}
instead of {:error, reason} so Oban stops retrying immediately.
124 lines
3.6 KiB
Elixir
124 lines
3.6 KiB
Elixir
defmodule Microwaveprop.Workers.HrrrFetchWorkerTest do
|
|
use Microwaveprop.DataCase, async: true
|
|
|
|
alias Microwaveprop.Weather
|
|
alias Microwaveprop.Weather.HrrrProfile
|
|
alias Microwaveprop.Workers.HrrrFetchWorker
|
|
|
|
@sample_profile [
|
|
%{"pres" => 1000.0, "hght" => 110.0, "tmpc" => 25.0, "dwpc" => 18.0},
|
|
%{"pres" => 975.0, "hght" => 350.0, "tmpc" => 23.0, "dwpc" => 16.0},
|
|
%{"pres" => 950.0, "hght" => 590.0, "tmpc" => 21.0, "dwpc" => 14.0}
|
|
]
|
|
|
|
@sample_client_result %{
|
|
surface_temp_c: 25.0,
|
|
surface_dewpoint_c: 18.0,
|
|
surface_pressure_mb: 1013.0,
|
|
hpbl_m: 1500.0,
|
|
pwat_mm: 25.0,
|
|
run_time: ~U[2026-03-28 18:00:00Z],
|
|
profile: @sample_profile
|
|
}
|
|
|
|
describe "perform/1" do
|
|
test "skips if HRRR profile already exists" do
|
|
Weather.upsert_hrrr_profile(%{
|
|
valid_time: ~U[2026-03-28 18:00:00Z],
|
|
lat: 32.90,
|
|
lon: -97.04,
|
|
profile: @sample_profile
|
|
})
|
|
|
|
job =
|
|
HrrrFetchWorker.new(%{
|
|
"lat" => 32.90,
|
|
"lon" => -97.04,
|
|
"valid_time" => "2026-03-28T18:00:00Z"
|
|
})
|
|
|
|
assert :ok = HrrrFetchWorker.perform(%Oban.Job{args: job.changes.args})
|
|
end
|
|
|
|
test "stores profile when client returns success" do
|
|
# We test the perform logic by mocking at the module level
|
|
# The actual HTTP calls are tested in HrrrClientTest
|
|
# Here we verify the worker's coordination logic
|
|
|
|
lat = 32.90
|
|
lon = -97.04
|
|
valid_time = ~U[2026-03-28 18:00:00Z]
|
|
|
|
# Verify no profile exists initially
|
|
refute Weather.has_hrrr_profile?(lat, lon, valid_time)
|
|
|
|
# Simulate what perform does after a successful fetch
|
|
attrs = build_profile_attrs(lat, lon, valid_time, @sample_client_result)
|
|
{:ok, profile} = Weather.upsert_hrrr_profile(attrs)
|
|
|
|
assert profile.lat == lat
|
|
assert profile.lon == lon
|
|
assert profile.hpbl_m == 1500.0
|
|
assert profile.surface_temp_c == 25.0
|
|
assert Weather.has_hrrr_profile?(lat, lon, valid_time)
|
|
end
|
|
|
|
test "rounds lat/lon before checking existence" do
|
|
# Profile at rounded coordinates
|
|
Weather.upsert_hrrr_profile(%{
|
|
valid_time: ~U[2026-03-28 18:00:00Z],
|
|
lat: 32.90,
|
|
lon: -97.04,
|
|
profile: []
|
|
})
|
|
|
|
# Worker called with slightly different coords that round to same
|
|
job =
|
|
HrrrFetchWorker.new(%{
|
|
"lat" => 32.904,
|
|
"lon" => -97.039,
|
|
"valid_time" => "2026-03-28T18:00:00Z"
|
|
})
|
|
|
|
# Should skip because rounded coords match
|
|
assert :ok = HrrrFetchWorker.perform(%Oban.Job{args: job.changes.args})
|
|
|
|
# Only one profile should exist
|
|
count = Repo.aggregate(HrrrProfile, :count)
|
|
assert count == 1
|
|
end
|
|
end
|
|
|
|
describe "permanent_failure?/1" do
|
|
test "cancels on 404 idx" do
|
|
job = %Oban.Job{
|
|
args: %{
|
|
"lat" => 32.90,
|
|
"lon" => -97.04,
|
|
"valid_time" => "1995-06-15T12:00:00Z"
|
|
}
|
|
}
|
|
|
|
Req.Test.stub(Microwaveprop.Weather.HrrrClient, fn conn ->
|
|
Plug.Conn.send_resp(conn, 404, "not found")
|
|
end)
|
|
|
|
assert {:cancel, "HRRR idx HTTP 404"} = HrrrFetchWorker.perform(job)
|
|
end
|
|
end
|
|
|
|
defp build_profile_attrs(lat, lon, valid_time, client_result) do
|
|
%{
|
|
valid_time: valid_time,
|
|
lat: lat,
|
|
lon: lon,
|
|
run_time: client_result.run_time,
|
|
profile: client_result.profile,
|
|
hpbl_m: client_result.hpbl_m,
|
|
pwat_mm: client_result.pwat_mm,
|
|
surface_temp_c: client_result.surface_temp_c,
|
|
surface_dewpoint_c: client_result.surface_dewpoint_c,
|
|
surface_pressure_mb: client_result.surface_pressure_mb
|
|
}
|
|
end
|
|
end
|