Files
siftlode/backend/app
peter f73e097b39 feat(downloads): M2 — worker download loop + cache/dedup
- downloads/formats.py: profile spec -> format_sig (cache key) + yt-dlp opts (format
  selector, audio extract, sponsorblock, embed subs/chapters/thumbnail, jpg poster)
- downloads/storage.py: Plex tree path ({Channel}/Season {Year}/… [id].ext) + .nfo +
  poster.jpg sidecars; sanitization; asset-file deletion with empty-dir pruning
- downloads/service.py: enqueue + get-or-create shared MediaAsset (race-safe) + instant
  cache-hit path (ready asset -> job done, ref_count++)
- worker.py: N claim-loop threads (FOR UPDATE SKIP LOCKED), asset compare-and-set
  pending->downloading so identical requests never double-download, throttled progress
  writes, cooperative pause/cancel via the progress hook, crash-safe orphan recovery

Verified on localdev: real download -> Plex tree + .nfo + poster on the host bind-mount,
correct metadata/codecs/size; 2nd user = instant cache hit (shared asset, ref_count=2);
audio-only MP3 extraction path produces a distinct cached asset.
2026-07-03 00:08:18 +02:00
..
2026-06-14 04:40:22 +02:00