Fix stale PubSub subscriptions on record navigation
Subscription management was only done in mount/3, meaning
navigating to a different record via handle_params/3 left the
old subscription active. A background update for the old record
would then overwrite the currently displayed record.
Fix: manage subscriptions in handle_params/3 (unsubscribe old,
subscribe new) via shared RecordActions.manage_subscription/2,
and guard handle_info({:update,...}) against mismatched IDs.
This commit is contained in:
@@ -110,6 +110,14 @@ defmodule MusicLibrary.Records do
|
|||||||
Phoenix.PubSub.subscribe(MusicLibrary.PubSub, "records:#{record_id}")
|
Phoenix.PubSub.subscribe(MusicLibrary.PubSub, "records:#{record_id}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Unsubscribes the calling process from updates for a given record.
|
||||||
|
"""
|
||||||
|
@spec unsubscribe(String.t()) :: :ok | {:error, term()}
|
||||||
|
def unsubscribe(record_id) do
|
||||||
|
Phoenix.PubSub.unsubscribe(MusicLibrary.PubSub, "records:#{record_id}")
|
||||||
|
end
|
||||||
|
|
||||||
@spec notify_update(Record.t()) :: :ok | {:error, term()}
|
@spec notify_update(Record.t()) :: :ok | {:error, term()}
|
||||||
def notify_update(record) do
|
def notify_update(record) do
|
||||||
Phoenix.PubSub.broadcast(
|
Phoenix.PubSub.broadcast(
|
||||||
|
|||||||
@@ -348,11 +348,7 @@ defmodule MusicLibraryWeb.CollectionLive.Show do
|
|||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def mount(%{"id" => record_id}, _session, socket) do
|
def mount(_params, _session, socket) do
|
||||||
if connected?(socket) do
|
|
||||||
Records.subscribe(record_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
{:ok,
|
{:ok,
|
||||||
socket
|
socket
|
||||||
|> assign(:current_section, :collection)
|
|> assign(:current_section, :collection)
|
||||||
@@ -362,6 +358,8 @@ defmodule MusicLibraryWeb.CollectionLive.Show do
|
|||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def handle_params(%{"id" => id}, _, socket) do
|
def handle_params(%{"id" => id}, _, socket) do
|
||||||
|
RecordActions.manage_subscription(socket, id)
|
||||||
|
|
||||||
record = Records.get_record!(id)
|
record = Records.get_record!(id)
|
||||||
last_listened_track = ListeningStats.get_last_listened_track(record)
|
last_listened_track = ListeningStats.get_last_listened_track(record)
|
||||||
play_count = ListeningStats.play_count(record)
|
play_count = ListeningStats.play_count(record)
|
||||||
@@ -474,10 +472,14 @@ defmodule MusicLibraryWeb.CollectionLive.Show do
|
|||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def handle_info({:update, record}, socket) do
|
def handle_info({:update, record}, socket) do
|
||||||
{:noreply,
|
if record.id == socket.assigns.record.id do
|
||||||
socket
|
{:noreply,
|
||||||
|> RecordActions.handle_record_updated(record)
|
socket
|
||||||
|> assign_similar_records()}
|
|> RecordActions.handle_record_updated(record)
|
||||||
|
|> assign_similar_records()}
|
||||||
|
else
|
||||||
|
{:noreply, socket}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp page_title(action, record) do
|
defp page_title(action, record) do
|
||||||
|
|||||||
@@ -284,13 +284,9 @@ defmodule MusicLibraryWeb.WishlistLive.Show do
|
|||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def mount(%{"id" => record_id}, _session, socket) do
|
def mount(_params, _session, socket) do
|
||||||
current_date = DateTime.utc_now() |> DateTime.to_date()
|
current_date = DateTime.utc_now() |> DateTime.to_date()
|
||||||
|
|
||||||
if connected?(socket) do
|
|
||||||
Records.subscribe(record_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
{:ok,
|
{:ok,
|
||||||
socket
|
socket
|
||||||
|> assign(current_section: :wishlist)
|
|> assign(current_section: :wishlist)
|
||||||
@@ -299,6 +295,8 @@ defmodule MusicLibraryWeb.WishlistLive.Show do
|
|||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def handle_params(%{"id" => id}, _, socket) do
|
def handle_params(%{"id" => id}, _, socket) do
|
||||||
|
RecordActions.manage_subscription(socket, id)
|
||||||
|
|
||||||
record = Records.get_record!(id)
|
record = Records.get_record!(id)
|
||||||
online_store_templates = OnlineStoreTemplates.list_enabled_templates()
|
online_store_templates = OnlineStoreTemplates.list_enabled_templates()
|
||||||
|
|
||||||
@@ -367,7 +365,11 @@ defmodule MusicLibraryWeb.WishlistLive.Show do
|
|||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def handle_info({:update, record}, socket) do
|
def handle_info({:update, record}, socket) do
|
||||||
{:noreply, RecordActions.handle_record_updated(socket, record)}
|
if record.id == socket.assigns.record.id do
|
||||||
|
{:noreply, RecordActions.handle_record_updated(socket, record)}
|
||||||
|
else
|
||||||
|
{:noreply, socket}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp page_title(action, record) do
|
defp page_title(action, record) do
|
||||||
|
|||||||
@@ -97,6 +97,20 @@ defmodule MusicLibraryWeb.LiveHelpers.RecordActions do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Manages PubSub subscriptions when navigating between records.
|
||||||
|
Unsubscribes from the previous record (if any) and subscribes to the new one,
|
||||||
|
but only when the socket is connected.
|
||||||
|
"""
|
||||||
|
def manage_subscription(socket, new_id) do
|
||||||
|
if Phoenix.LiveView.connected?(socket) do
|
||||||
|
if socket.assigns[:record], do: Records.unsubscribe(socket.assigns.record.id)
|
||||||
|
Records.subscribe(new_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
def handle_chats_changed(socket) do
|
def handle_chats_changed(socket) do
|
||||||
{:noreply,
|
{:noreply,
|
||||||
assign(socket, :chat_count, Chats.count_chats(:record, socket.assigns.record.musicbrainz_id))}
|
assign(socket, :chat_count, Chats.count_chats(:record, socket.assigns.record.musicbrainz_id))}
|
||||||
|
|||||||
Reference in New Issue
Block a user