diff --git a/web_server.py b/web_server.py index a2551791..bcc4640f 100644 --- a/web_server.py +++ b/web_server.py @@ -209,8 +209,6 @@ class WebUIDownloadMonitor: def _monitor_loop(self): """Main monitoring loop - checks downloads every 1 second for responsive web UX""" - import time - while self.monitoring and self.monitored_batches: try: self._check_all_downloads() @@ -314,7 +312,7 @@ class WebUIDownloadMonitor: return False else: queue_time = current_time - task['queued_start_time'] - if queue_time > 90: + if queue_time > 120: # Increased timeout to reduce retry spam # Track retry attempts to prevent rapid loops retry_count = task.get('stuck_retry_count', 0) last_retry = task.get('last_retry_time', 0) @@ -333,6 +331,9 @@ class WebUIDownloadMonitor: print(f"❌ Task failed after 3 retry attempts (queue timeout)") task['status'] = 'failed' task['error_message'] = 'Failed after multiple queue timeout retries' + # Clear timers to prevent further retry loops + task.pop('queued_start_time', None) + task.pop('downloading_start_time', None) return False # Check for downloading at 0% timeout (90 seconds like GUI) @@ -342,7 +343,7 @@ class WebUIDownloadMonitor: return False else: download_time = current_time - task['downloading_start_time'] - if download_time > 90: + if download_time > 120: # Increased timeout to reduce retry spam retry_count = task.get('stuck_retry_count', 0) last_retry = task.get('last_retry_time', 0) @@ -359,6 +360,9 @@ class WebUIDownloadMonitor: print(f"❌ Task failed after 3 retry attempts (0% progress timeout)") task['status'] = 'failed' task['error_message'] = 'Failed after multiple 0% progress retries' + # Clear timers to prevent further retry loops + task.pop('queued_start_time', None) + task.pop('downloading_start_time', None) return False else: # Progress being made, reset timers and retry counts @@ -404,21 +408,21 @@ class WebUIDownloadMonitor: # Only attempt cancellation if we have what looks like a proper download ID # (not a filename fallback which would be much longer) - if download_id and username and len(download_id) < 100: - print(f"🚫 Attempting to cancel stuck download: {os.path.basename(download_id)} from {username} (task: {task_id[:8]}...)") + if download_id and username and isinstance(download_id, str) and len(download_id) < 100: + print(f"🚫 Attempting to cancel stuck download: {os.path.basename(str(download_id))} from {username} (task: {task_id[:8]}...)") try: success = asyncio.run(soulseek_client.cancel_download(download_id, username, remove=False)) if success: - print(f"✅ Successfully cancelled download {download_id[:8]}... from {username}") + print(f"✅ Successfully cancelled download {str(download_id)[:8]}... from {username}") # Clear any stored download info to prevent status conflicts task.pop('soulseek_download_id', None) task.pop('soulseek_username', None) else: - print(f"⚠️ Cancel request failed for {download_id[:8]}... - all API endpoints returned errors, proceeding with retry anyway") + print(f"⚠️ Cancel request failed for {str(download_id)[:8]}... - all API endpoints returned errors, proceeding with retry anyway") except Exception as e: - print(f"⚠️ Cancel exception for {download_id[:8]}...: {str(e)[:150]}, proceeding with retry anyway") + print(f"⚠️ Cancel exception for {str(download_id)[:8]}...: {str(e)[:150]}, proceeding with retry anyway") else: - print(f"⚠️ Invalid download ID for cancellation (len={len(download_id) if download_id else 0}, username={bool(username)}), proceeding with retry") + print(f"⚠️ Skipping cancellation - invalid data (ID len={len(str(download_id)) if download_id else 0}, username='{username}'), proceeding with retry") except Exception as e: print(f"⚠️ Error in cancellation logic, proceeding with retry: {e}") @@ -469,7 +473,6 @@ def cleanup_monitor(): download_monitor.monitoring = False download_monitor.monitored_batches.clear() # Give the thread a moment to exit cleanly - import time time.sleep(0.5) def signal_handler(signum, frame): @@ -2054,7 +2057,6 @@ def check_artist_discography_completion_stream(artist_id): yield f"data: {json.dumps(completion_data)}\n\n" # Small delay to make the streaming effect visible - import time time.sleep(0.1) # 100ms delay between items except Exception as e: @@ -7321,7 +7323,6 @@ def _run_sync_task(playlist_id, playlist_name, tracks_json): """The actual sync function that runs in the background thread.""" global sync_states, sync_service - import time task_start_time = time.time() print(f"🚀 [TIMING] _run_sync_task STARTED for playlist '{playlist_name}' at {time.strftime('%H:%M:%S')}") print(f"📊 Received {len(tracks_json)} tracks from frontend") @@ -7528,7 +7529,6 @@ def _run_sync_task(playlist_id, playlist_name, tracks_json): @app.route('/api/sync/start', methods=['POST']) def start_playlist_sync(): """Starts a new sync process for a given playlist.""" - import time request_start_time = time.time() print(f"⏱️ [TIMING] Sync request received at {time.strftime('%H:%M:%S')}")