soulsync/core/automation/handlers
BoulderBadgeDad de20897f83 Fix: deep-scan / DB-update automation falsely errors on large libraries (stall-based timeout)
The DB-update + deep-scan automation monitor used a hard 2-hour TOTAL cap
(while elapsed < 7200). It tracked progress but only used it to print a stall
warning — the only thing that actually timed out was wall-clock. So a large
library that scans for >2h while progressing fine (reported: 4781 artists) trips
the cap and the automation card flips to 'error: timed out after 2 hours' even
though the scan thread is healthy and still running (the timeout never cancels
it, which is why it keeps progressing in the logs after the 'error').

Time out on STALL, not total runtime:
- 30 min with NO progress -> error ('stalled'); catches a genuinely hung scan.
- 10 min idle -> warning (repeats); unchanged heads-up.
- 24h absolute backstop, purely a runaway-loop guard.
- An actively-progressing scan keeps resetting the idle clock, so it never
  times out no matter how many hours the whole library takes.
- Progress is judged on (processed, progress, current_item) so a slow stretch
  where the rounded % holds steady (but the artist keeps changing) isn't a
  false stall.

The decision is extracted into a pure, testable scan_wait_action(); both the
deep-scan and full-refresh handlers share the monitor loop, so both are fixed.

Tests: tests/test_scan_wait_action.py (9) — headline regression (5h/12h total
but progressing -> 'continue', not timeout), finished/stall-warn/stall-timeout/
abs-cap thresholds, and ordering. 280 automation tests still pass.
2026-06-01 16:30:28 -07:00
..
__init__.py Personalized playlist pipeline: auto-sync discover-page playlists 2026-05-15 18:41:08 -07:00
_pipeline_shared.py Harden playlist pipeline source refresh 2026-05-24 19:31:00 -07:00
database_update.py Fix: deep-scan / DB-update automation falsely errors on large libraries (stall-based timeout) 2026-06-01 16:30:28 -07:00
discover_playlist.py Extract automation handlers (2/N): playlist lifecycle group 2026-05-15 10:47:46 -07:00
download_cleanup.py Extract automation handlers (3/3): maintenance + misc, finishing the lift 2026-05-15 11:24:35 -07:00
duplicate_cleaner.py Extract automation handlers (3/3): maintenance + misc, finishing the lift 2026-05-15 11:24:35 -07:00
maintenance.py DB backups: verify integrity + never evict the last good backup 2026-05-30 21:13:04 -07:00
personalized_pipeline.py Preserve personalized playlist metadata for wishlist 2026-05-15 21:50:32 -07:00
playlist_pipeline.py Move mirrored playlist pipeline into playlist domain 2026-05-24 19:44:13 -07:00
process_wishlist.py Extract automation handlers (1/N): infrastructure + 3 simple handlers 2026-05-15 10:25:41 -07:00
progress_callbacks.py Extract automation handlers (4/3 — finish): progress callbacks + scan-completion emitter 2026-05-15 11:59:32 -07:00
quality_scanner.py Extract automation handlers (3/3): maintenance + misc, finishing the lift 2026-05-15 11:24:35 -07:00
refresh_mirrored.py Auto-Sync: fix LB pipelines stuck on "Refreshing:" for 5+ minutes 2026-05-27 18:04:55 -07:00
registration.py Personalized playlist pipeline: auto-sync discover-page playlists 2026-05-15 18:41:08 -07:00
run_script.py Extract automation handlers (3/3): maintenance + misc, finishing the lift 2026-05-15 11:24:35 -07:00
scan_library.py Extract automation handlers (1/N): infrastructure + 3 simple handlers 2026-05-15 10:25:41 -07:00
scan_watchlist.py Extract automation handlers (1/N): infrastructure + 3 simple handlers 2026-05-15 10:25:41 -07:00
search_and_download.py Extract automation handlers (3/3): maintenance + misc, finishing the lift 2026-05-15 11:24:35 -07:00
sync_playlist.py Extract automation handlers (2/N): playlist lifecycle group 2026-05-15 10:47:46 -07:00