ML-188: guard PubSub record updates during edit mode

Add live_action guard to handle_info({:update, record}) in both
CollectionLive.Show and WishlistLive.Show. When the user is editing,
background worker updates are skipped and a warning toast is shown
instead of overwriting the socket. Normal show-mode updates and
mismatched-ID no-ops are unchanged.

6 tests added covering all three code paths.
This commit is contained in:
Claudio Ortolina
2026-05-19 11:38:42 +01:00
parent 2fca0bb106
commit e204e555bd
9 changed files with 236 additions and 27 deletions
@@ -472,13 +472,25 @@ defmodule MusicLibraryWeb.CollectionLive.Show do
@impl true
def handle_info({:update, record}, socket) do
if record.id == socket.assigns.record.id do
{:noreply,
socket
|> RecordActions.handle_record_updated(record)
|> assign_similar_records()}
else
{:noreply, socket}
cond do
record.id != socket.assigns.record.id ->
{:noreply, socket}
socket.assigns.live_action == :edit ->
{:noreply,
socket
|> put_toast(
:warning,
gettext(
"Record was updated in the background. Your edits may be stale — save and re-open to see the latest data."
)
)}
true ->
{:noreply,
socket
|> RecordActions.handle_record_updated(record)
|> assign_similar_records()}
end
end
@@ -365,10 +365,22 @@ defmodule MusicLibraryWeb.WishlistLive.Show do
@impl true
def handle_info({:update, record}, socket) do
if record.id == socket.assigns.record.id do
{:noreply, RecordActions.handle_record_updated(socket, record)}
else
{:noreply, socket}
cond do
record.id != socket.assigns.record.id ->
{:noreply, socket}
socket.assigns.live_action == :edit ->
{:noreply,
socket
|> put_toast(
:warning,
gettext(
"Record was updated in the background. Your edits may be stale — save and re-open to see the latest data."
)
)}
true ->
{:noreply, RecordActions.handle_record_updated(socket, record)}
end
end
@@ -119,6 +119,10 @@ defmodule MusicLibraryWeb.LiveHelpers.RecordActions do
@doc """
Handles a background record update. Returns the updated socket (not wrapped
in `{:noreply, ...}`) so the caller can pipe additional assigns.
**Note:** Callers intentionally bypass this function when `live_action == :edit`
to prevent background worker updates from overwriting the user's in-progress
form edits. See CollectionLive.Show and WishlistLive.Show `handle_info({:update, record})`.
"""
def handle_record_updated(socket, record) do
socket