Commit Graph

4 Commits

Author SHA1 Message Date
Myron Blair ef5c13d587 Fix Library Cleanup scan freezing the entire server
scan() was doing hundreds of blocking Path.is_file()/stat() calls directly
in an async function -- movie/episode/track files often live on the
NFS/CIFS-mounted NAS, so each stat call has real network latency. Since
the backend runs a single-threaded asyncio event loop, this froze every
other request (confirmed live: a plain GET /api/movies hung for 60s+ while
a cleanup scan was in flight) for as long as the scan took.

Moved every filesystem-touching check (missing files, orphaned HLS dirs)
into a plain sync function run via asyncio.to_thread, so the scan can no
longer block anything else.
2026-07-26 22:35:37 -05:00
Myron Blair 5fc37e46e4 Fix 8 code-review findings across transcode queue, requests, cleanup, music
- Episode transcode (single + bulk) now accepts storage_type=scan, matching
  stream_episode and the movie-transcode endpoint — Library-Scan-imported
  TV episodes can finally be transcoded, not just streamed.
- retry_job now forwards content_type, fixing retry for failed/cancelled
  episode jobs (was silently treating them as movies and failing again).
- cancel_job now updates the correct collection (movies vs episodes) based
  on content_type instead of always writing to db.movies.
- approve_request atomically claims the request (pending -> approving)
  before contacting Radarr/Sonarr, so a double-click or two concurrent
  admins can't both add the same content; releases the claim back to
  pending on any failure so a fixable error can be retried.
- Music enrichment's update_many now re-checks album_art_url is still
  empty, so it no longer clobbers art an admin manually set via PATCH.
- Library Cleanup's dangling-refs scan now also checks episode_progress
  for rows referencing a deleted episode (previously only watchlist/
  progress against movie_id were checked).
- Settings now surfaces a failed bulk-TMDB-enrich run as an error instead
  of a false "Enrichment done" success summary.
- Music player's isPlaying now syncs from the audio element's native
  play/pause events instead of only being set inside togglePlay/track-
  change, so it can't drift from actual playback state (buffering stalls,
  OS media-key pauses, etc).
2026-07-26 22:24:09 -05:00
Myron Blair 5ac78654d4 Code review fix: Library Cleanup left orphaned rows on episode delete
Fixing a missing-file or duplicate-import episode only deleted the
episode itself, leaving its episode_progress/subtitle rows behind for
the next scan to catch as separate orphaned_subtitles/dangling findings.
Consolidated movie/episode/track deletion (with all their dependent rows)
into one _delete_content() helper, used consistently by missing_files,
orphaned_episodes, and duplicate_paths.
2026-07-26 22:11:05 -05:00
Myron Blair c174ac60b1 Add Library Cleanup admin page — missing files, orphaned records, stuck jobs, duplicates
New read-only scan (GET /api/library/cleanup/scan) across movies, episodes,
tracks, subtitles, HLS output, transcode queue, and watchlist/progress rows:
- Missing files: DB record exists but the file is gone from disk
- Orphaned episodes: show_id no longer exists
- Orphaned HLS output: transcoded folders left behind by deleted content
- Stuck transcode jobs: "running" 2+ hours with no completion (backend-restart artifact)
- Duplicate imports: same file imported into the library more than once
- Orphaned subtitles / dangling watchlist+progress rows

Nothing is deleted until an admin clicks Fix (per-item or Fix All per
category) via POST /api/library/cleanup/fix.
2026-07-26 21:13:16 -05:00