4.8 KiB
id, title, status, assignee, created_date, updated_date, labels, dependencies, documentation, modified_files, priority, ordinal
| id | title | status | assignee | created_date | updated_date | labels | dependencies | documentation | modified_files | priority | ordinal | |||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ML-190 | Skip redundant unsubscribe+resubscribe on same-record reconnect | To Do | 2026-05-19 08:42 | 2026-05-19 09:26 |
|
|
|
low | 25000 |
Description
RecordActions.manage_subscription/2 unsubscribes the old record and subscribes the new record on every handle_params call. When LiveView reconnects to the same record (e.g., after a WebSocket drop within the reconnect grace period), it unsubscribes and resubscribes to the same topic. While harmless (Phoenix.PubSub deduplicates by PID), a same-record check would be a micro-optimization.
Fix: Add a guard: if socket.assigns[:record] && socket.assigns.record.id != new_id, do: Records.unsubscribe(...) — only unsubscribe when the record actually changes.
Source: Audit doc-25 (Phase 2), Recommendation #2.
Acceptance Criteria
- #1 manage_subscription/2 only calls unsubscribe when old record ID differs from new ID
- #2 Same-record reconnect skips unsubscribe+resubscribe entirely
- #3 All existing tests pass
Implementation Plan
Overview
Micro-optimization to skip the redundant Records.unsubscribe/1 call when a LiveView reconnects to the same record. The change is a single guard addition in RecordActions.manage_subscription/2. No other modules are affected.
Nature: Code hygiene, not a measurable performance win. The skip eliminates at most two ETS operations on reconnect, which Phoenix.PubSub already deduplicates by PID internally.
Callers (no changes needed)
| LiveView | File | Line | Hook |
|---|---|---|---|
| CollectionLive.Show | lib/music_library_web/live/collection_live/show.ex |
361 | handle_params/3 |
| WishlistLive.Show | lib/music_library_web/live/wishlist_live/show.ex |
298 | handle_params/3 |
Both call manage_subscription(socket, id) at the top of handle_params/3 before loading the record. No caller changes are needed because the function signature and return value (:ok) remain unchanged.
Code change
File: lib/music_library_web/live_helpers/record_actions.ex
Change the unsubscribe guard from:
if socket.assigns[:record], do: Records.unsubscribe(socket.assigns.record.id)
to:
if socket.assigns[:record] && socket.assigns.record.id != new_id,
do: Records.unsubscribe(socket.assigns.record.id)
The Records.subscribe(new_id) call is intentionally left unconditional: on same-record reconnect it's a no-op (PubSub deduplicates by PID), and on first mount it's required.
Edge-case coverage
| Scenario | socket.assigns[:record] |
old vs new | Unsub? | Sub? | Correct? |
|---|---|---|---|---|---|
| First mount | nil |
short-circuits | No | Yes | ✅ |
| Navigate to different record | record A | A ≠ B | Yes | Yes | ✅ |
| Reconnect same record | record X | X == X | No | Yes (no-op) | ✅ |
Verification steps
-
Run existing tests:
mix test test/music_library_web/live_helpers/record_actions_test.exs mix test test/music_library_web/live/collection_live/show_test.exs mix test test/music_library_web/live/wishlist_live/show_test.exsAll should pass. These cover
manage_subscription/2indirectly through PubSub broadcast handling and full page navigation tests. -
Manual reconnect smoke test (optional): Navigate to a record show page, kill the server, restart it, and confirm the page reconnects and continues to receive PubSub updates (e.g., trigger a background cover refresh and verify the toast appears).
-
No new test is strictly required. The change is a pure optimization — it removes a redundant call that was already harmless. Existing PubSub broadcast tests in
record_actions_test.exs(thehandle_record_updateddescribe block) confirm the subscription lifecycle works end-to-end.
Documentation
- No user-facing docs need updating.
- The
@docformanage_subscription/2is already accurate and does not need amendment. - No production infrastructure changes, environment variables, or migrations are required.