fix: pskreporter — eliminate @spots crash, duplicate stream IDs, and slow aggregate blocking with start_async

This commit is contained in:
Graham McInitre 2026-07-16 08:36:00 -05:00
parent 5eeac23e83
commit e6018c6fd9

View file

@ -16,18 +16,35 @@ defmodule MicrowavepropWeb.PskrSpotsLive do
_ = if connected?(socket), do: schedule_refresh() _ = if connected?(socket), do: schedule_refresh()
spots = fetch_recent_spots() spots = fetch_recent_spots()
socket = start_async(socket, :total_spots, fn -> fetch_total_spots() end)
socket = start_async(socket, :band_counts, fn -> fetch_band_counts() end)
{:ok, {:ok,
socket socket
|> assign( |> assign(
page_title: "PSK Reporter Spots", page_title: "PSK Reporter Spots",
limit: @limit, limit: @limit,
total_spots: fetch_total_spots(), total_spots: nil,
band_counts: fetch_band_counts() band_counts: [],
spots_empty: spots == []
) )
|> stream(:spots, spots, reset: true)} |> stream(:spots, spots, reset: true)}
end end
@impl true
def handle_async(:total_spots, {:ok, total}, socket) do
{:noreply, assign(socket, total_spots: total)}
end
def handle_async(:band_counts, {:ok, counts}, socket) do
{:noreply, assign(socket, band_counts: counts)}
end
def handle_async(slot, {:exit, reason}, socket) do
Logger.warning("PskrSpotsLive async #{slot} failed: #{inspect(reason)}")
{:noreply, socket}
end
@impl true @impl true
def handle_info(:refresh_spots, socket) do def handle_info(:refresh_spots, socket) do
_ = schedule_refresh() _ = schedule_refresh()
@ -37,7 +54,8 @@ defmodule MicrowavepropWeb.PskrSpotsLive do
socket socket
|> assign( |> assign(
total_spots: fetch_total_spots(), total_spots: fetch_total_spots(),
band_counts: fetch_band_counts() band_counts: fetch_band_counts(),
spots_empty: spots == []
) )
|> stream(:spots, spots, reset: true)} |> stream(:spots, spots, reset: true)}
end end
@ -112,13 +130,6 @@ defmodule MicrowavepropWeb.PskrSpotsLive do
</tr> </tr>
</thead> </thead>
<tbody id="pskr-spots" phx-update="stream"> <tbody id="pskr-spots" phx-update="stream">
<tr
:for={{dom_id, spot} <- @streams.spots}
id={dom_id}
class="hidden only:table-row"
>
No spots yet
</tr>
<tr :for={{dom_id, spot} <- @streams.spots} id={dom_id}> <tr :for={{dom_id, spot} <- @streams.spots} id={dom_id}>
<td class="text-xs font-mono">{fmt_dt(spot.last_spot_at)}</td> <td class="text-xs font-mono">{fmt_dt(spot.last_spot_at)}</td>
<td class="text-xs"><span class="badge badge-sm">{spot.band}</span></td> <td class="text-xs"><span class="badge badge-sm">{spot.band}</span></td>
@ -141,7 +152,7 @@ defmodule MicrowavepropWeb.PskrSpotsLive do
</table> </table>
</div> </div>
<p :if={@spots == []} class="text-sm text-base-content/50 italic mt-4"> <p :if={@spots_empty && @total_spots == 0} class="text-sm text-base-content/50 italic mt-4">
No PSK Reporter spots received yet. The MQTT listener is running spots will appear here as they arrive. No PSK Reporter spots received yet. The MQTT listener is running spots will appear here as they arrive.
</p> </p>
</Layouts.app> </Layouts.app>