fix(contact): stop loading-flash on already-enriched contacts
Two related fixes:
- Drop the global contact_enrichment:{hrrr,weather,solar} subscriptions.
These topics fire for every QSO's enrichment completion, and the
handlers blindly re-queried data for the currently-displayed contact,
causing spurious re-renders whenever any enrichment worker finished
anywhere in the system. The per-contact terrain subscription stays —
that one is correctly scoped.
- Only add a slot to `hydration_pending` when the contact's status
column says the work is genuinely in flight (:queued or :processing).
Previously every connected mount flashed spinners over all eight
enrichment sections, even for contacts whose data was already cached
and about to return instantly from the async task.
Also drop the Donate-to-NTMS footer link.
This commit is contained in:
parent
871582ee09
commit
cf6812f154
2 changed files with 20 additions and 77 deletions
|
|
@ -100,16 +100,6 @@ defmodule MicrowavepropWeb.Layouts do
|
|||
North Texas Microwave Society
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
Found this useful?
|
||||
<a
|
||||
href="https://www.paypal.com/ncp/payment/53VLBD2E67JAE"
|
||||
target="_blank"
|
||||
class="link link-hover"
|
||||
>
|
||||
Donate to NTMS
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<.link navigate="/privacy" class="link link-hover">Privacy</.link>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -74,9 +74,6 @@ defmodule MicrowavepropWeb.ContactLive.Show do
|
|||
socket =
|
||||
if connected?(socket) do
|
||||
Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "contact_enrichment:#{contact.id}")
|
||||
Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "contact_enrichment:hrrr")
|
||||
Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "contact_enrichment:weather")
|
||||
Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "contact_enrichment:solar")
|
||||
|
||||
kickoff_hydration(socket, contact)
|
||||
else
|
||||
|
|
@ -91,19 +88,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do
|
|||
# clauses below update the matching slot and re-run the derived analysis.
|
||||
defp kickoff_hydration(socket, contact) do
|
||||
socket
|
||||
|> assign(
|
||||
:hydration_pending,
|
||||
MapSet.new([
|
||||
:weather,
|
||||
:solar,
|
||||
:hrrr_path,
|
||||
:narr_path,
|
||||
:native_profile,
|
||||
:terrain,
|
||||
:iemre,
|
||||
:radar
|
||||
])
|
||||
)
|
||||
|> assign(:hydration_pending, pending_slots(contact))
|
||||
|> start_async(:weather, fn -> load_weather(contact) end)
|
||||
|> start_async(:solar, fn -> load_solar(contact) end)
|
||||
|> start_async(:hrrr_path, fn -> Weather.hrrr_profiles_for_path(contact) end)
|
||||
|
|
@ -114,6 +99,25 @@ defmodule MicrowavepropWeb.ContactLive.Show do
|
|||
|> start_async(:radar, fn -> load_radar(contact) end)
|
||||
end
|
||||
|
||||
# A slot shows its loading spinner only while the corresponding enrichment
|
||||
# column on the contact says the work is genuinely in flight. For contacts
|
||||
# whose status is :complete (or :pending/:unavailable/:failed), the async
|
||||
# query just returns whatever is cached without any intermediate flash.
|
||||
defp pending_slots(contact) do
|
||||
in_flight = [:queued, :processing]
|
||||
slots = []
|
||||
slots = if contact.weather_status in in_flight, do: [:weather | slots], else: slots
|
||||
|
||||
slots =
|
||||
if contact.hrrr_status in in_flight,
|
||||
do: [:hrrr_path, :narr_path, :native_profile | slots],
|
||||
else: slots
|
||||
|
||||
slots = if contact.terrain_status in in_flight, do: [:terrain | slots], else: slots
|
||||
slots = if contact.iemre_status in in_flight, do: [:iemre | slots], else: slots
|
||||
MapSet.new(slots)
|
||||
end
|
||||
|
||||
defp mark_hydrated(socket, slot) do
|
||||
assign(socket, :hydration_pending, MapSet.delete(socket.assigns.hydration_pending, slot))
|
||||
end
|
||||
|
|
@ -458,57 +462,6 @@ defmodule MicrowavepropWeb.ContactLive.Show do
|
|||
)}
|
||||
end
|
||||
|
||||
def handle_info({:hrrr_ready, _info}, socket) do
|
||||
contact = socket.assigns.contact
|
||||
hrrr_path = Weather.hrrr_profiles_for_path(contact)
|
||||
hrrr = List.first(hrrr_path)
|
||||
|
||||
if hrrr do
|
||||
contact = %{contact | hrrr_status: :complete}
|
||||
soundings = socket.assigns.soundings
|
||||
terrain = socket.assigns.terrain
|
||||
elevation_profile = compute_elevation_profile(contact, hrrr_path, soundings)
|
||||
propagation_analysis = build_propagation_analysis(contact, hrrr_path, terrain, elevation_profile, soundings)
|
||||
|
||||
{:noreply,
|
||||
assign(socket,
|
||||
contact: contact,
|
||||
hrrr: hrrr,
|
||||
queue_counts: fetch_queue_counts(),
|
||||
elevation_profile: elevation_profile,
|
||||
propagation_analysis: propagation_analysis
|
||||
)}
|
||||
else
|
||||
{:noreply, socket}
|
||||
end
|
||||
end
|
||||
|
||||
def handle_info({:weather_ready, _info}, socket) do
|
||||
contact = %{socket.assigns.contact | weather_status: :complete}
|
||||
weather = load_weather(contact)
|
||||
soundings = weather.soundings
|
||||
|
||||
hrrr_path = Weather.hrrr_profiles_for_path(contact)
|
||||
terrain = socket.assigns.terrain
|
||||
|
||||
elevation_profile = compute_elevation_profile(contact, hrrr_path, soundings)
|
||||
propagation_analysis = build_propagation_analysis(contact, hrrr_path, terrain, elevation_profile, soundings)
|
||||
|
||||
{:noreply,
|
||||
assign(socket,
|
||||
contact: contact,
|
||||
surface_observations: weather.surface_observations,
|
||||
soundings: soundings,
|
||||
elevation_profile: elevation_profile,
|
||||
propagation_analysis: propagation_analysis
|
||||
)}
|
||||
end
|
||||
|
||||
def handle_info({:solar_ready, _date}, socket) do
|
||||
solar = load_solar(socket.assigns.contact)
|
||||
{:noreply, assign(socket, solar: solar)}
|
||||
end
|
||||
|
||||
defp maybe_enqueue_weather(weather, contact) do
|
||||
has_data = weather.surface_observations != [] or weather.soundings != []
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue