diff --git a/lib/microwaveprop/propagation/pipeline_status.ex b/lib/microwaveprop/propagation/pipeline_status.ex index 13a923a4..cffe5751 100644 --- a/lib/microwaveprop/propagation/pipeline_status.ex +++ b/lib/microwaveprop/propagation/pipeline_status.ex @@ -36,13 +36,27 @@ defmodule Microwaveprop.Propagation.PipelineStatus do last_update_at: DateTime.t() | nil } + @doc """ + Format a forecast-progress payload (as broadcast by + `PropagationGridWorker`) into a short chip label for the map. + + Returns `nil` when the payload has no `forecast_hour` so callers can + fall back to the base running label from `current/0`. + """ + @spec running_label(map() | nil) :: String.t() | nil + def running_label(%{forecast_hour: 0}), do: "Updating propagation · now" + + def running_label(%{forecast_hour: fh}) when is_integer(fh) and fh > 0, do: "Updating propagation · +#{fh}h" + + def running_label(_), do: nil + @spec current() :: t() def current do case running_worker() do worker when is_binary(worker) -> %{ state: :running, - label: running_label(worker), + label: base_running_label(worker), last_update_at: latest_completed_at() } @@ -97,9 +111,9 @@ defmodule Microwaveprop.Propagation.PipelineStatus do end end - defp running_label(@grid_worker), do: "Updating propagation (HRRR run)" - defp running_label(@asos_worker), do: "Updating propagation (ASOS nudge)" - defp running_label(_), do: "Updating propagation" + defp base_running_label(@grid_worker), do: "Updating propagation (HRRR run)" + defp base_running_label(@asos_worker), do: "Updating propagation (ASOS nudge)" + defp base_running_label(_), do: "Updating propagation" defp format_age(0), do: "just now" defp format_age(1), do: "1m" diff --git a/lib/microwaveprop/workers/propagation_grid_worker.ex b/lib/microwaveprop/workers/propagation_grid_worker.ex index 5405accb..549e2104 100644 --- a/lib/microwaveprop/workers/propagation_grid_worker.ex +++ b/lib/microwaveprop/workers/propagation_grid_worker.ex @@ -84,6 +84,14 @@ defmodule Microwaveprop.Workers.PropagationGridWorker do defp process_forecast_hour(points, run_time, forecast_hour, valid_time) do label = "f#{String.pad_leading(Integer.to_string(forecast_hour), 2, "0")}" + # Emit progress so the map page's pipeline status chip can show + # which forecast hour is currently being scored ("now", "+1h", …). + Phoenix.PubSub.broadcast( + Microwaveprop.PubSub, + "propagation:pipeline", + {:propagation_pipeline_progress, %{forecast_hour: forecast_hour, valid_time: valid_time}} + ) + case timed(label, fn -> HrrrClient.fetch_grid(points, run_time, forecast_hour: forecast_hour) end) do diff --git a/lib/microwaveprop_web/live/map_live.ex b/lib/microwaveprop_web/live/map_live.ex index 6e720a27..20b8ce62 100644 --- a/lib/microwaveprop_web/live/map_live.ex +++ b/lib/microwaveprop_web/live/map_live.ex @@ -24,6 +24,7 @@ defmodule MicrowavepropWeb.MapLive do def mount(_params, session, socket) do if connected?(socket) do Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "propagation:updated") + Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "propagation:pipeline") Process.send_after(self(), :refresh_pipeline_status, @pipeline_status_refresh_ms) end @@ -31,6 +32,7 @@ defmodule MicrowavepropWeb.MapLive do socket |> assign(:initial_utc_clock, Calendar.strftime(DateTime.utc_now(), "%H:%M UTC")) |> assign(:pipeline_status, PipelineStatus.current()) + |> assign(:pipeline_progress, nil) # LiveStash only persists the keys passed to `stash_assigns/2` # (selected_band + selected_time). On reconnect the recovered socket has @@ -283,7 +285,24 @@ defmodule MicrowavepropWeb.MapLive do def handle_info(:refresh_pipeline_status, socket) do Process.send_after(self(), :refresh_pipeline_status, @pipeline_status_refresh_ms) - {:noreply, assign(socket, :pipeline_status, PipelineStatus.current())} + + new_status = PipelineStatus.current() + + progress = + if new_status.state == :running do + socket.assigns[:pipeline_progress] + end + + socket = + socket + |> assign(:pipeline_status, new_status) + |> assign(:pipeline_progress, progress) + + {:noreply, socket} + end + + def handle_info({:propagation_pipeline_progress, progress}, socket) do + {:noreply, assign(socket, :pipeline_progress, progress)} end @impl true @@ -362,14 +381,17 @@ defmodule MicrowavepropWeb.MapLive do attr :id, :string, required: true attr :status, :map, required: true + attr :progress, :any, default: nil defp pipeline_status_chip(assigns) do + assigns = assign(assigns, :display_label, chip_display_label(assigns.status, assigns.progress)) + ~H"""