From 349d653ca0969ac4c10f0880834b9fe3fd626000 Mon Sep 17 00:00:00 2001 From: Broque Thomas Date: Sun, 7 Dec 2025 14:43:43 -0800 Subject: [PATCH] Prevent race conditions in wishlist downloads Adds support for sending specific track IDs from the frontend to the backend when starting wishlist missing downloads. This ensures only the tracks currently visible to the user are processed, preventing race conditions if the wishlist changes between modal open and analysis start. Category filtering remains for backward compatibility. --- web_server.py | 18 ++++++++++++++++-- webui/static/script.js | 8 +++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/web_server.py b/web_server.py index 49999570..4b3a2447 100644 --- a/web_server.py +++ b/web_server.py @@ -8294,6 +8294,7 @@ def start_wishlist_missing_downloads(): data = request.get_json() or {} force_download_all = data.get('force_download_all', False) category = data.get('category') # Get category filter (albums or singles) + track_ids = data.get('track_ids') # NEW: Get specific track IDs from frontend from core.wishlist_service import get_wishlist_service from database.music_database import MusicDatabase @@ -8371,8 +8372,21 @@ def start_wishlist_missing_downloads(): print(f"🔧 [Manual-Wishlist] Sanitized {len(wishlist_tracks)} tracks from wishlist service") - # FILTER BY CATEGORY if specified (same logic as auto-processing) - if category: + # FILTER BY TRACK IDs if specified (prioritized - prevents race conditions) + if track_ids: + # Convert to set for O(1) lookup + track_id_set = set(track_ids) + filtered_tracks = [] + for track in wishlist_tracks: + spotify_track_id = track.get('spotify_track_id') or track.get('id') + if spotify_track_id in track_id_set: + filtered_tracks.append(track) + + wishlist_tracks = filtered_tracks + print(f"🎯 [Manual-Wishlist] Filtered to {len(wishlist_tracks)} specific tracks by ID (preventing race condition)") + + # FILTER BY CATEGORY if specified and no track_ids (backward compatibility) + elif category: import json filtered_tracks = [] for track in wishlist_tracks: diff --git a/webui/static/script.js b/webui/static/script.js index 8e7c5342..048b56e7 100644 --- a/webui/static/script.js +++ b/webui/static/script.js @@ -5529,12 +5529,18 @@ async function startWishlistMissingTracksProcess(playlistId) { forceToggleContainer.style.display = 'none'; } + // Extract track IDs from what the user is currently seeing in the modal + // This prevents race conditions where wishlist changes between modal open and analysis start + const trackIds = process.tracks ? process.tracks.map(t => t.spotify_track_id || t.id).filter(id => id) : null; + console.log(`🎯 [Wishlist] Sending ${trackIds ? trackIds.length : 'all'} specific track IDs to prevent race condition`); + const response = await fetch('/api/wishlist/download_missing', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ force_download_all: forceDownloadAll, - category: window.currentWishlistCategory // Pass category to backend + category: window.currentWishlistCategory, // Keep for backward compat + track_ids: trackIds // NEW: Send exact tracks to process }) });