Revert "Refactor watchlist auto-scanning to use heartbeat thread"
This reverts commit 5f03641b7d.
This commit is contained in:
parent
5f03641b7d
commit
6b7877edab
1 changed files with 34 additions and 88 deletions
122
web_server.py
122
web_server.py
|
|
@ -251,8 +251,7 @@ wishlist_timer_lock = threading.Lock() # Thread safety for timer operations
|
|||
|
||||
# --- Automatic Watchlist Scanning Infrastructure ---
|
||||
# Server-side timer system for automatic watchlist scanning (mirrors wishlist pattern for consistency)
|
||||
watchlist_scheduler_thread = None # background thread
|
||||
watchlist_stop_event = threading.Event()
|
||||
watchlist_auto_timer = None # threading.Timer for scheduling next auto-scanning
|
||||
watchlist_auto_scanning = False # Flag to prevent concurrent auto-scanning
|
||||
watchlist_auto_scanning_timestamp = 0 # Timestamp when scanning started (for stuck detection)
|
||||
watchlist_next_run_time = 0 # Timestamp when next auto-scanning is scheduled (for countdown display)
|
||||
|
|
@ -17459,99 +17458,47 @@ watchlist_scan_state = {
|
|||
'error': None
|
||||
}
|
||||
|
||||
def _watchlist_heartbeat_loop():
|
||||
"""
|
||||
Background heartbeat loop that triggers watchlist scanning every 24 hours.
|
||||
Allows for robust retry logic when conflicts occur with the wishlist processor.
|
||||
"""
|
||||
print("💓 [Auto-Watchlist] Heartbeat scheduler started")
|
||||
|
||||
# Initial delay of 5 minutes
|
||||
if watchlist_stop_event.wait(300):
|
||||
return
|
||||
|
||||
while not watchlist_stop_event.is_set():
|
||||
try:
|
||||
# Run the processing logic
|
||||
# Returns: 'completed', 'skipped_conflict', 'skipped_idle', 'skipped_active'
|
||||
result = _process_watchlist_scan_automatically()
|
||||
|
||||
if result == 'skipped_conflict':
|
||||
# If conflict with wishlist, wait 10 minutes and retry
|
||||
print("⏳ [Auto-Watchlist] Pausing 10 minutes before retry due to wishlist conflict")
|
||||
|
||||
# Update UI timer
|
||||
with watchlist_timer_lock:
|
||||
watchlist_next_run_time = time.time() + 600.0
|
||||
|
||||
if watchlist_stop_event.wait(600):
|
||||
break
|
||||
else:
|
||||
# Standard 24 hour cycle for success or other skips
|
||||
with watchlist_timer_lock:
|
||||
watchlist_next_run_time = time.time() + 86400.0
|
||||
|
||||
if watchlist_stop_event.wait(86400):
|
||||
break
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ [Auto-Watchlist] Error in heartbeat loop: {e}")
|
||||
# Wait 10 minutes on error before retrying to avoid spamming
|
||||
with watchlist_timer_lock:
|
||||
watchlist_next_run_time = time.time() + 600.0
|
||||
|
||||
if watchlist_stop_event.wait(600):
|
||||
break
|
||||
|
||||
def start_watchlist_auto_scanning():
|
||||
"""Start automatic watchlist scanning with robust heartbeat scheduler."""
|
||||
global watchlist_scheduler_thread, watchlist_next_run_time
|
||||
|
||||
# Reset stop event
|
||||
watchlist_stop_event.clear()
|
||||
"""Start automatic watchlist scanning with 5-minute initial delay (Timer-based like wishlist)"""
|
||||
global watchlist_auto_timer, watchlist_next_run_time
|
||||
|
||||
print("🚀 [Auto-Watchlist] Initializing automatic watchlist scanning...")
|
||||
|
||||
with watchlist_timer_lock:
|
||||
# Stop any existing thread
|
||||
if watchlist_scheduler_thread is not None and watchlist_scheduler_thread.is_alive():
|
||||
print("⚠️ Watchlist scheduler already running")
|
||||
return
|
||||
# Stop any existing timer to prevent duplicates
|
||||
if watchlist_auto_timer is not None:
|
||||
watchlist_auto_timer.cancel()
|
||||
|
||||
print("🔄 Starting automatic watchlist heartbeat system (5 minute initial delay)")
|
||||
print("🔄 Starting automatic watchlist scanning system (5 minute initial delay)")
|
||||
watchlist_next_run_time = time.time() + 300.0 # Set timestamp for countdown display
|
||||
|
||||
watchlist_scheduler_thread = threading.Thread(target=_watchlist_heartbeat_loop, daemon=True, name="WatchlistHeartbeat")
|
||||
watchlist_scheduler_thread.start()
|
||||
print(f"✅ [Auto-Watchlist] Heartbeat thread started successfully")
|
||||
watchlist_auto_timer = threading.Timer(300.0, _process_watchlist_scan_automatically) # 5 minutes
|
||||
watchlist_auto_timer.daemon = True
|
||||
watchlist_auto_timer.start()
|
||||
print(f"✅ [Auto-Watchlist] Timer started successfully - will trigger in 5 minutes")
|
||||
|
||||
def stop_watchlist_auto_scanning():
|
||||
"""Stop automatic watchlist scanning and cleanup thread."""
|
||||
global watchlist_scheduler_thread, watchlist_auto_scanning, watchlist_auto_scanning_timestamp, watchlist_next_run_time
|
||||
"""Stop automatic watchlist scanning and cleanup timer."""
|
||||
global watchlist_auto_timer, watchlist_auto_scanning
|
||||
|
||||
with watchlist_timer_lock:
|
||||
# Signal thread to stop
|
||||
watchlist_stop_event.set()
|
||||
|
||||
if watchlist_scheduler_thread is not None:
|
||||
watchlist_scheduler_thread = None
|
||||
if watchlist_auto_timer is not None:
|
||||
watchlist_auto_timer.cancel()
|
||||
watchlist_auto_timer = None
|
||||
print("⏹️ Stopped automatic watchlist scanning")
|
||||
|
||||
watchlist_auto_scanning = False
|
||||
watchlist_auto_scanning_timestamp = 0
|
||||
watchlist_next_run_time = 0
|
||||
|
||||
def schedule_next_watchlist_scan():
|
||||
"""
|
||||
Update the UI timestamp for the next run.
|
||||
NOTE: The actual scheduling is now handled by _watchlist_heartbeat_loop.
|
||||
This function exists to update the UI countdown.
|
||||
"""
|
||||
global watchlist_next_run_time
|
||||
"""Schedule next automatic watchlist scan in 24 hours."""
|
||||
global watchlist_auto_timer, watchlist_next_run_time
|
||||
|
||||
with watchlist_timer_lock:
|
||||
print("⏰ [UI Update] Updating next watchlist scan timestamp (handled by heartbeat)")
|
||||
print("⏰ Scheduling next automatic watchlist scan in 24 hours")
|
||||
watchlist_next_run_time = time.time() + 86400.0 # Set timestamp for countdown display
|
||||
watchlist_auto_timer = threading.Timer(86400.0, _process_watchlist_scan_automatically) # 24 hours
|
||||
watchlist_auto_timer.daemon = True
|
||||
watchlist_auto_timer.start()
|
||||
|
||||
def _process_watchlist_scan_automatically():
|
||||
"""Main automatic scanning logic that runs in background thread."""
|
||||
|
|
@ -17563,19 +17510,19 @@ def _process_watchlist_scan_automatically():
|
|||
with watchlist_timer_lock:
|
||||
if watchlist_auto_scanning:
|
||||
print("⚠️ Watchlist auto-scanning already running, skipping.")
|
||||
# We return 'skipped_active' so heartbeat knows we're busy but alive
|
||||
# Heartbeat will wait 24h as per normal cycle since it's already running
|
||||
schedule_next_watchlist_scan()
|
||||
return 'skipped_active'
|
||||
schedule_next_watchlist_scan()
|
||||
return
|
||||
|
||||
# Check if wishlist processing is currently running (using smart detection)
|
||||
if is_wishlist_actually_processing():
|
||||
print("🎵 Wishlist processing in progress, rescheduling watchlist scan for 10 minutes from now")
|
||||
# Just update UI timer. Heartbeat loop will handle the 10m wait and retry.
|
||||
global watchlist_next_run_time
|
||||
with watchlist_timer_lock:
|
||||
watchlist_next_run_time = time.time() + 600.0
|
||||
return 'skipped_conflict'
|
||||
# Smart retry: don't wait 24 hours, just wait 10 minutes and try again
|
||||
global watchlist_auto_timer, watchlist_next_run_time
|
||||
watchlist_next_run_time = time.time() + 600.0 # Set timestamp for countdown display
|
||||
watchlist_auto_timer = threading.Timer(600.0, _process_watchlist_scan_automatically) # 10 minutes
|
||||
watchlist_auto_timer.daemon = True
|
||||
watchlist_auto_timer.start()
|
||||
return
|
||||
|
||||
# Set flag and timestamp
|
||||
import time
|
||||
|
|
@ -17599,7 +17546,7 @@ def _process_watchlist_scan_automatically():
|
|||
watchlist_auto_scanning = False
|
||||
watchlist_auto_scanning_timestamp = 0
|
||||
schedule_next_watchlist_scan()
|
||||
return 'skipped_idle'
|
||||
return
|
||||
|
||||
if not spotify_client or not spotify_client.is_authenticated():
|
||||
print("ℹ️ [Auto-Watchlist] Spotify client not available or not authenticated.")
|
||||
|
|
@ -17857,8 +17804,6 @@ def _process_watchlist_scan_automatically():
|
|||
if total_added_to_wishlist > 0:
|
||||
add_activity_item("👁️", "Watchlist Scan Complete", f"{total_added_to_wishlist} new tracks added to wishlist", "Now")
|
||||
|
||||
return 'completed'
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error in automatic watchlist scan: {e}")
|
||||
import traceback
|
||||
|
|
@ -17868,10 +17813,11 @@ def _process_watchlist_scan_automatically():
|
|||
watchlist_scan_state['error'] = str(e)
|
||||
|
||||
finally:
|
||||
# Always reset flag
|
||||
# Always reset flag and schedule next scan
|
||||
with watchlist_timer_lock:
|
||||
watchlist_auto_scanning = False
|
||||
watchlist_auto_scanning_timestamp = 0
|
||||
schedule_next_watchlist_scan()
|
||||
|
||||
print("✅ Automatic watchlist scanning initialized")
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue