From 3c06e66f03e3dfaf0b9ff928b4142a5a3223ec5a Mon Sep 17 00:00:00 2001 From: JohnBaumb <80135794+JohnBaumb@users.noreply.github.com> Date: Wed, 22 Apr 2026 11:59:12 -0700 Subject: [PATCH] fix: downloads page album art, total count, and clear-completed safety - Fix missing album art on downloads page across all sources - Fix downloads page showing wrong total count - Enrich missing download artwork from metadata cache - Prevent Clear Completed from removing active download batches - Keep download limit at 300 per performance design --- web_server.py | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/web_server.py b/web_server.py index 7adbe3a2..249f7a2e 100644 --- a/web_server.py +++ b/web_server.py @@ -31402,6 +31402,34 @@ def get_all_downloads_unified(): # Sort: active first (by priority), then by timestamp desc within each group items.sort(key=lambda x: (x['priority'], -x['timestamp'])) + # POST-LOCK: Enrich missing artwork from metadata cache (handles legacy + # wishlist tracks that were stored without image data) + items_needing_art = [it for it in items if not it.get('artwork') and it.get('title')] + if items_needing_art: + try: + database = get_database() + # Batch lookup by track name — metadata cache has deezer/itunes images + track_names = list({it['title'] for it in items_needing_art if it['title']}) + if track_names: + placeholders = ','.join('?' for _ in track_names) + with database._get_connection() as conn: + cursor = conn.cursor() + cursor.execute(f""" + SELECT name, image_url FROM metadata_cache_entities + WHERE entity_type='track' AND name IN ({placeholders}) + AND image_url IS NOT NULL AND image_url != '' + """, track_names) + name_to_art = {} + for row in cursor.fetchall(): + if row[0] not in name_to_art: + name_to_art[row[0]] = row[1] + for it in items_needing_art: + cached_url = name_to_art.get(it['title']) + if cached_url: + it['artwork'] = cached_url + except Exception as cache_err: + logger.debug(f"Metadata cache artwork lookup failed: {cache_err}") + # Build batch summaries for the batch context panel batch_summaries = [] with tasks_lock: @@ -31462,9 +31490,16 @@ def clear_completed_downloads(): for tid in task_ids_to_remove: del download_tasks[tid] cleared += 1 - # Also clean up empty batches + # Also clean up empty batches (but not those still actively processing) + active_phases = {'analysis', 'downloading', 'queued'} empty_batches = [] for bid, batch in download_batches.items(): + # Never remove batches that are still actively working + if batch.get('phase') in active_phases: + # Still prune cleared tasks from queue + remaining = [t for t in batch.get('queue', []) if t in download_tasks] + batch['queue'] = remaining + continue remaining = [t for t in batch.get('queue', []) if t in download_tasks] if not remaining: empty_batches.append(bid)