fix(web): serialize addTrackToPlaylist saga to stop dropping bulk-added tracks#14422
fix(web): serialize addTrackToPlaylist saga to stop dropping bulk-added tracks#14422dylanjeffers wants to merge 1 commit into
Conversation
…racks The saga used `takeEvery`, so two ADD_TRACK_TO_PLAYLIST dispatches in close succession would run concurrently. Each invocation read the cached playlist, mutated a local copy to append its track, and only wrote the result back after `updatePlaylistArtwork` finished (canvas image generation, often 100–300ms). When a second saga read between the first saga's read and write, both captured the same "N tracks" baseline; both wrote "N+1", each with only their own added track; the later write won and dropped the earlier track. The confirmer's SDK update used the same captured-stale playlist, so the backend lost the missing tracks too. This was reproducible via the add-tracks-by-URL modal — 5 pasted URLs would often land as just 1 track in the playlist, both in the UI and on refresh. The modal's 30ms inter-dispatch delay was a workaround that couldn't cover the full artwork-generation window. Switch to an actionChannel + serial take loop so adds for the same (or different) playlists process one-at-a-time. Each saga now sees the prior saga's optimistic update before reading its own baseline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
🌐 Web preview readyPreview URL: https://audius-web-preview-pr-14422.audius.workers.dev Unique preview for this PR (deployed from this branch). |
|
Closing — diagnosis was wrong. The user has confirmed the failing flow is single-track add via the track menu / drag-drop (not bulk paste-URL), and the bug started in the last 1–2 days, which doesn't match the pre-existing concurrency race this PR addresses. Re-investigating. |
Summary
addTrackToPlaylistsaga usedtakeEveryso concurrent dispatches raced: each captured the cached playlist, mutated locally, then wrote back only after the slowupdatePlaylistArtworkfinished. With overlapping sagas, the later write overwrote the earlier one with a captured-stale playlist, dropping the earlier added track on both the cache and the backend (the confirmer's SDK update used the same captured playlist).actionChannel+ a serialtakeloop so each add runs to completion (cache write + confirmer queued) before the next one starts reading.Test plan
🤖 Generated with Claude Code