From e15f581b33c3bf7c8ee979579b582ed0c37f1622 Mon Sep 17 00:00:00 2001 From: Broque Thomas <26755000+Nezreka@users.noreply.github.com> Date: Tue, 21 Apr 2026 16:30:43 -0700 Subject: [PATCH] Fix enrichment worker pause being silently undone after downloads finish MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User reported pausing the Spotify/Last.fm/Genius enrichment worker via the dashboard bubble would silently turn back on "by itself". Real cause was a race in the download-yield auto-pause/resume loop (_emit_enrichment_worker_stats_loop): 1. Download starts. Loop sees worker running, auto-pauses it, adds its name to _download_auto_paused. 2. User clicks the enrichment bubble to pause — already paused visually, but they want it to STAY off. Pause endpoint sets config_manager '_enrichment_paused' to True and calls worker.pause() — but does not remove the name from _download_auto_paused. 3. Download finishes. Loop sees 'not downloading and name in _download_auto_paused' and blindly flips w.paused = False, overriding the user's explicit pause. Config still says paused, but the worker is actually running. Two defensive fixes: - Auto-resume block now checks the user's persisted config intent before flipping the worker on. If {name}_enrichment_paused is True in config, the name is dropped from _download_auto_paused without touching w.paused — user's pause stays honored. - Pause endpoints for spotify-enrichment, lastfm-enrichment, and genius-enrichment now also discard from _download_auto_paused so a stale marker can't trigger this race again. Both together mean the auto-pause loop can no longer override a manual pause regardless of ordering. Full suite stays at 263 passed. Ruff clean. --- web_server.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/web_server.py b/web_server.py index fc635658..d087ed37 100644 --- a/web_server.py +++ b/web_server.py @@ -51619,6 +51619,9 @@ def spotify_enrichment_pause(): spotify_enrichment_worker.pause() config_manager.set('spotify_enrichment_paused', True) + # Drop any auto-pause marker so the post-download resume loop won't + # override this explicit user pause. + _download_auto_paused.discard('spotify-enrichment') logger.info("Spotify enrichment worker paused via UI") return jsonify({'status': 'paused'}), 200 except Exception as e: @@ -51778,6 +51781,9 @@ def lastfm_enrichment_pause(): lastfm_worker.pause() config_manager.set('lastfm_enrichment_paused', True) + # Drop any auto-pause marker so the post-download resume loop won't + # override this explicit user pause. + _download_auto_paused.discard('lastfm-enrichment') logger.info("Last.fm worker paused via UI") return jsonify({'status': 'paused'}), 200 except Exception as e: @@ -51921,6 +51927,9 @@ def genius_enrichment_pause(): genius_worker.pause() config_manager.set('genius_enrichment_paused', True) + # Drop any auto-pause marker so the post-download resume loop won't + # override this explicit user pause. + _download_auto_paused.discard('genius-enrichment') logger.info("Genius worker paused via UI") return jsonify({'status': 'paused'}), 200 except Exception as e: @@ -54425,9 +54434,17 @@ def _emit_enrichment_status_loop(): _download_auto_paused.add(name) logger.debug(f"Auto-paused {name} during active downloads") elif not downloading and name in _download_auto_paused: - w.paused = False + # Don't override an explicit user pause. If config says the worker + # was paused via the UI, leave it paused and just drop the auto-pause + # marker so the next auto-pause/resume cycle behaves normally. + config_key = f"{name.replace('-', '_')}_paused" + user_paused = config_manager.get(config_key, False) _download_auto_paused.discard(name) - logger.debug(f"Auto-resumed {name} after downloads finished") + if not user_paused: + w.paused = False + logger.debug(f"Auto-resumed {name} after downloads finished") + else: + logger.debug(f"Downloads finished but {name} remains paused by user") except Exception as e: logger.debug(f"Error in download-yield check: {e}")