Refactor wishlist auto-processing to use heartbeat thread
Replaces the previous daisy-chained timer logic for automatic wishlist processing with a robust background heartbeat thread. This ensures reliable scheduling, simplifies stopping/starting, and improves error handling. UI countdown updates remain compatible with existing call sites.
This commit is contained in:
parent
97161856e7
commit
238abb2aea
1 changed files with 55 additions and 21 deletions
|
|
@ -8836,32 +8836,64 @@ def is_watchlist_actually_scanning():
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
wishlist_scheduler_thread = None
|
||||||
|
wishlist_stop_event = threading.Event()
|
||||||
|
|
||||||
|
def _wishlist_heartbeat_loop():
|
||||||
|
"""
|
||||||
|
Background heartbeat loop that triggers wishlist processing every 30 minutes.
|
||||||
|
This replaces the fragile daisy-chained logic to ensure the timer never dies.
|
||||||
|
"""
|
||||||
|
print("💓 [Auto-Wishlist] Heartbeat scheduler started")
|
||||||
|
|
||||||
|
# Initial delay of 1 minute
|
||||||
|
if wishlist_stop_event.wait(60):
|
||||||
|
return
|
||||||
|
|
||||||
|
while not wishlist_stop_event.is_set():
|
||||||
|
try:
|
||||||
|
# Run the processing logic
|
||||||
|
_process_wishlist_automatically()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ [Auto-Wishlist] Error in heartbeat loop: {e}")
|
||||||
|
|
||||||
|
# Wait for 30 minutes (1800 seconds) or until stopped
|
||||||
|
if wishlist_stop_event.wait(1800):
|
||||||
|
break
|
||||||
|
|
||||||
def start_wishlist_auto_processing():
|
def start_wishlist_auto_processing():
|
||||||
"""Start automatic wishlist processing with 1-minute initial delay."""
|
"""Start automatic wishlist processing with robust heartbeat scheduler."""
|
||||||
global wishlist_auto_timer, wishlist_next_run_time
|
global wishlist_scheduler_thread, wishlist_next_run_time
|
||||||
|
|
||||||
|
# Reset stop event
|
||||||
|
wishlist_stop_event.clear()
|
||||||
|
|
||||||
print("🚀 [Auto-Wishlist] Initializing automatic wishlist processing...")
|
print("🚀 [Auto-Wishlist] Initializing automatic wishlist processing...")
|
||||||
|
|
||||||
with wishlist_timer_lock:
|
with wishlist_timer_lock:
|
||||||
# Stop any existing timer to prevent duplicates
|
# Stop any existing thread/timer
|
||||||
if wishlist_auto_timer is not None:
|
if wishlist_scheduler_thread is not None and wishlist_scheduler_thread.is_alive():
|
||||||
wishlist_auto_timer.cancel()
|
print("⚠️ Wishlist scheduler already running")
|
||||||
|
return
|
||||||
|
|
||||||
print("🔄 Starting automatic wishlist processing system (1 minute initial delay)")
|
print("🔄 Starting automatic wishlist heartbeat system (1 minute initial delay)")
|
||||||
wishlist_next_run_time = time.time() + 60.0 # Set timestamp for countdown display
|
wishlist_next_run_time = time.time() + 60.0 # Set timestamp for countdown display
|
||||||
wishlist_auto_timer = threading.Timer(60.0, _process_wishlist_automatically) # 1 minute
|
|
||||||
wishlist_auto_timer.daemon = True
|
wishlist_scheduler_thread = threading.Thread(target=_wishlist_heartbeat_loop, daemon=True, name="WishlistHeartbeat")
|
||||||
wishlist_auto_timer.start()
|
wishlist_scheduler_thread.start()
|
||||||
print(f"✅ [Debug] Timer started successfully - will trigger in 60 seconds")
|
print(f"✅ [Debug] Heartbeat thread started successfully")
|
||||||
|
|
||||||
def stop_wishlist_auto_processing():
|
def stop_wishlist_auto_processing():
|
||||||
"""Stop automatic wishlist processing and cleanup timer."""
|
"""Stop automatic wishlist processing and cleanup thread."""
|
||||||
global wishlist_auto_timer, wishlist_auto_processing, wishlist_auto_processing_timestamp, wishlist_next_run_time
|
global wishlist_scheduler_thread, wishlist_auto_processing, wishlist_auto_processing_timestamp, wishlist_next_run_time
|
||||||
|
|
||||||
with wishlist_timer_lock:
|
with wishlist_timer_lock:
|
||||||
if wishlist_auto_timer is not None:
|
# Signal thread to stop
|
||||||
wishlist_auto_timer.cancel()
|
wishlist_stop_event.set()
|
||||||
wishlist_auto_timer = None
|
|
||||||
|
if wishlist_scheduler_thread is not None:
|
||||||
|
# We don't join() here to avoid blocking the UI, the thread will exit on next wake
|
||||||
|
wishlist_scheduler_thread = None
|
||||||
print("⏹️ Stopped automatic wishlist processing")
|
print("⏹️ Stopped automatic wishlist processing")
|
||||||
|
|
||||||
wishlist_auto_processing = False
|
wishlist_auto_processing = False
|
||||||
|
|
@ -8869,15 +8901,17 @@ def stop_wishlist_auto_processing():
|
||||||
wishlist_next_run_time = 0 # Clear countdown timer
|
wishlist_next_run_time = 0 # Clear countdown timer
|
||||||
|
|
||||||
def schedule_next_wishlist_processing():
|
def schedule_next_wishlist_processing():
|
||||||
"""Schedule next automatic wishlist processing in 30 minutes."""
|
"""
|
||||||
global wishlist_auto_timer, wishlist_next_run_time
|
Update the UI timestamp for the next run.
|
||||||
|
NOTE: The actual scheduling is now handled by _wishlist_heartbeat_loop.
|
||||||
|
This function exists to maintain compatibility with existing call sites
|
||||||
|
and ensure the UI countdown is accurate.
|
||||||
|
"""
|
||||||
|
global wishlist_next_run_time
|
||||||
|
|
||||||
with wishlist_timer_lock:
|
with wishlist_timer_lock:
|
||||||
print("⏰ Scheduling next automatic wishlist processing in 30 minutes")
|
print("⏰ [UI Update] Updating next run timestamp (handled by heartbeat)")
|
||||||
wishlist_next_run_time = time.time() + 1800.0 # Set timestamp for countdown display
|
wishlist_next_run_time = time.time() + 1800.0 # Set timestamp for countdown display
|
||||||
wishlist_auto_timer = threading.Timer(1800.0, _process_wishlist_automatically) # 30 minutes (1800 seconds)
|
|
||||||
wishlist_auto_timer.daemon = True
|
|
||||||
wishlist_auto_timer.start()
|
|
||||||
|
|
||||||
def _process_wishlist_automatically():
|
def _process_wishlist_automatically():
|
||||||
"""Main automatic processing logic that runs in background thread."""
|
"""Main automatic processing logic that runs in background thread."""
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue