Show queue position on all loading spinners, fix solar backfill

- Unified queue_info helper shows "(N jobs in queue)" on all spinners
- Solar index auto-enqueues when missing on contact page
- Freshness monitor disabled in dev
- Fix test stubs for solar client
This commit is contained in:
Graham McIntire 2026-04-02 16:17:31 -05:00
parent 0e089e8493
commit d36256e730
No known key found for this signature in database
GPG key ID: F4ABF488E6029E59
3 changed files with 33 additions and 26 deletions

View file

@ -77,7 +77,7 @@ config :microwaveprop, Oban,
{Oban.Plugins.Lifeline, rescue_after: to_timeout(minute: 30)},
{Oban.Plugins.Cron,
crontab: [
{"5 * * * *", Microwaveprop.Workers.PropagationGridWorker},
# {"5 * * * *", Microwaveprop.Workers.PropagationGridWorker},
{"0 8 * * *", Microwaveprop.Workers.SolarIndexWorker}
]}
]
@ -96,8 +96,8 @@ config :microwaveprop, load_ml_model: true
# Use local SRTM1 tiles for elevation lookups instead of the Open-Meteo API
config :microwaveprop, srtm_tiles_dir: Path.expand("~/srtm/tiles")
# Freshness monitor watches for stale propagation scores
config :microwaveprop, start_freshness_monitor: true
# Freshness monitor disabled in dev (no hourly propagation grid running)
config :microwaveprop, start_freshness_monitor: false
# Initialize plugs at runtime for faster development compilation
config :phoenix, :plug_init_mode, :runtime

View file

@ -34,7 +34,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do
solar = maybe_enqueue_solar(contact)
hrrr_path = Weather.hrrr_profiles_for_path(contact)
hrrr = List.first(hrrr_path)
{hrrr, contact, hrrr_jobs_ahead} = maybe_enqueue_hrrr(hrrr, contact)
{hrrr, contact} = maybe_enqueue_hrrr(hrrr, contact)
terrain = Terrain.get_terrain_profile(contact.id)
contact = maybe_enqueue_terrain(terrain, contact)
contact = maybe_enqueue_weather(weather, contact)
@ -60,7 +60,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do
obs_sort_order: "asc",
sounding_sort_by: "station_name",
sounding_sort_order: "asc",
hrrr_jobs_ahead: hrrr_jobs_ahead,
queue_counts: fetch_queue_counts(),
expanded_soundings: MapSet.new()
)}
end
@ -153,7 +153,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do
assign(socket,
contact: contact,
hrrr: hrrr,
hrrr_jobs_ahead: 0,
queue_counts: fetch_queue_counts(),
elevation_profile: elevation_profile,
propagation_analysis: propagation_analysis
)}
@ -313,7 +313,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do
Radio.set_enrichment_status!([contact.id], :hrrr_status, :complete)
end
{hrrr, %{contact | hrrr_status: :complete}, 0}
{hrrr, %{contact | hrrr_status: :complete}}
end
defp maybe_enqueue_hrrr(nil, contact) do
@ -324,8 +324,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do
valid_time = HrrrClient.nearest_hrrr_hour(contact.qso_timestamp)
{rlat, rlon} = Weather.round_to_hrrr_grid(lat, lon)
{:ok, job} =
Oban.insert(
Oban.insert(
HrrrFetchWorker.new(%{
"lat" => rlat,
"lon" => rlon,
@ -334,24 +333,31 @@ defmodule MicrowavepropWeb.ContactLive.Show do
)
Radio.set_enrichment_status!([contact.id], :hrrr_status, :queued)
jobs_ahead = if job.id, do: count_hrrr_jobs_ahead(job.id), else: 0
{nil, %{contact | hrrr_status: :queued}, jobs_ahead}
{nil, %{contact | hrrr_status: :queued}}
else
{nil, contact, 0}
{nil, contact}
end
end
defp count_hrrr_jobs_ahead(job_id) do
defp queue_info(counts, queue) do
case Map.get(counts, queue, 0) do
0 -> ""
1 -> "(1 job in queue)"
n -> "(#{n} jobs in queue)"
end
end
defp fetch_queue_counts do
import Ecto.Query
Microwaveprop.Repo.one(
Microwaveprop.Repo.all(
from(j in Oban.Job,
where: j.queue == "hrrr",
where: j.state in ["available", "scheduled", "retryable", "executing"],
where: j.id < ^job_id,
select: count(j.id)
group_by: j.queue,
select: {j.queue, count(j.id)}
)
)
|> Map.new()
end
defp load_solar(contact) do
@ -422,7 +428,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do
<%= if !@elevation_profile && @contact.terrain_status == :queued do %>
<div class="flex items-center gap-2 text-sm text-base-content/50 my-4">
<span class="loading loading-spinner loading-sm"></span>
Computing elevation profile and terrain analysis...
Computing elevation profile and terrain analysis {queue_info(@queue_counts, "terrain")}
</div>
<% end %>
@ -587,7 +593,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do
<div class="text-sm text-base-content/50 italic">
<%= if @contact.terrain_status == :queued do %>
<span class="flex items-center gap-2">
<span class="loading loading-spinner loading-sm"></span> Computing terrain profile...
<span class="loading loading-spinner loading-sm"></span> Computing terrain profile {queue_info(@queue_counts, "terrain")}
</span>
<% else %>
No terrain profile available.
@ -603,7 +609,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do
<%= if @contact.weather_status == :queued do %>
<span class="flex items-center gap-2">
<span class="loading loading-spinner loading-sm"></span>
Fetching sounding data from nearby stations...
Fetching sounding data from nearby stations {queue_info(@queue_counts, "weather")}
</span>
<% else %>
No soundings found nearby.
@ -687,7 +693,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do
<div class="text-sm text-base-content/50 italic">
<span class="flex items-center gap-2">
<span class="loading loading-spinner loading-sm"></span>
Fetching solar index data...
Fetching solar index data {queue_info(@queue_counts, "solar")}
</span>
</div>
<% end %>
@ -765,10 +771,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do
<% :queued -> %>
<span class="flex items-center gap-2">
<span class="loading loading-spinner loading-sm"></span>
Fetching HRRR atmospheric data
<%= if @hrrr_jobs_ahead > 0 do %>
({@hrrr_jobs_ahead} {if @hrrr_jobs_ahead == 1, do: "job", else: "jobs"} ahead in queue)
<% end %>
Fetching HRRR atmospheric data {queue_info(@queue_counts, "hrrr")}
</span>
<% :unavailable -> %>
HRRR data unavailable for this contact time.
@ -786,7 +789,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do
<%= if @contact.weather_status == :queued do %>
<span class="flex items-center gap-2">
<span class="loading loading-spinner loading-sm"></span>
Fetching surface observations from nearby stations...
Fetching surface observations from nearby stations {queue_info(@queue_counts, "weather")}...
</span>
<% else %>
No surface observations found nearby.

View file

@ -15,6 +15,10 @@ defmodule MicrowavepropWeb.ContactLiveTest do
Plug.Conn.send_resp(conn, 404, "not found")
end)
Req.Test.stub(Microwaveprop.Weather.SolarClient, fn conn ->
Req.Test.text(conn, "")
end)
:ok
end