2 months ago
99f9da8PR #1 of 8 for issue #151.
Routing fix:
- Add is_remote_stems() guard in load_playback_source_streaming that returns
Ok(None) before the is_remote() branch, so stems_remote songs bypass
resolve_song_file_path() (which fails because file_path is cleared by
update_remote_song). The caller falls back to the non-streaming
load_playback_source path that handles remote stems via
load_remote_stems_playback_source + ensure_remote_stem_files_cached.
Complete-set verification:
- Replace the old per-stem ensure_remote_file_cached loop (which downloaded
each stem independently to its final path with no validation and no
all-or-nothing semantics) with ensure_remote_stem_set_cached, a new
orchestrator that:
- Reads the StemCacheEntry to determine the required two-stem or four-stem set
- Downloads each missing stem to a unique temp path (.part.<stem>.<request_id>)
- Validates each downloaded stem by full decode (catches truncated and corrupt
files that a probe would miss)
- Requires the same sample_rate, channels, and PCM frame count across the set
- Atomically renames every verified temp file to its final path only after ALL
stems pass validation (all-or-nothing)
- Retains already-verified stems (final path exists + decodes) across retries
- Threads a request_id epoch for stale-guard structure (no-op in synchronous
PR #1; PR #7 will add the real async guard)
The old ensure_remote_stem_files_cached is now a thin wrapper that resolves the
active remote library + provider and delegates to ensure_remote_stem_set_cached.
Tests (10 new, all using a test-only FakeRemoteProvider + generated WAV files):
- stems_remote bypasses resolve_song_file_path in streaming path
- Two-stem and four-stem sets download every required file
- Missing, truncated, corrupt, and mismatched-sample-rate stems prevent the
entire set from installing (no final-path file is written)
- Already-verified stems are retained on retry (not re-downloaded)
- Stale download for song A does not overwrite song B's installed stems
Seams left for later PRs:
- TODO(PR#3): route through shared atomic download helper + durable catalog
- TODO(PR#7): add async stale-guard closure for request_id epoch checkParentf1610f5