Amazon download client: write final size==transferred before returning file path
The download monitor blocks post-processing with a bytes-incomplete guard: if size > 0 and transferred < size: continue _stream_to_file throttles engine updates to every 0.5s. The last tick before the file finishes typically leaves transferred slightly below the Content-Length size in the engine record. Other streaming clients (YouTube, Tidal, HiFi, etc.) use their own download threads and don't track bytes at all, so size stays 0 and the guard is always skipped. Amazon was the only client hitting it. Fix: just before returning the file path from _download_sync, write a final engine record update setting size == transferred == out_path.stat().st_size (the decrypted output size). The bytes-incomplete guard then sees transferred == size and falls through to trigger post-processing normally.
This commit is contained in:
parent
b4403ed393
commit
ff27effdae
2 changed files with 30 additions and 1 deletions
|
|
@ -285,10 +285,21 @@ class AmazonDownloadClient(DownloadSourcePlugin):
|
|||
else:
|
||||
enc_path.rename(out_path)
|
||||
|
||||
final_size = out_path.stat().st_size
|
||||
logger.info(
|
||||
f"Amazon download complete ({codec}): {out_path} "
|
||||
f"({out_path.stat().st_size / (1024 * 1024):.1f} MB)"
|
||||
f"({final_size / (1024 * 1024):.1f} MB)"
|
||||
)
|
||||
# Sync size == transferred so the download monitor's bytes-incomplete
|
||||
# guard doesn't block post-processing. The throttled updates in
|
||||
# _stream_to_file leave transferred < size after the last 0.5s tick;
|
||||
# other streaming clients avoid this by not tracking bytes at all
|
||||
# (size stays 0, the guard is skipped). Writing the final output size
|
||||
# here restores parity.
|
||||
if self._engine is not None:
|
||||
self._engine.update_record(
|
||||
"amazon", download_id, {'size': final_size, 'transferred': final_size}
|
||||
)
|
||||
return str(out_path)
|
||||
|
||||
logger.error(f"All codec tiers exhausted for '{display_name}' ({asin})")
|
||||
|
|
|
|||
|
|
@ -616,6 +616,24 @@ class TestDownloadSync:
|
|||
states = [c[0][2].get("state") for c in update_calls if "state" in c[0][2]]
|
||||
assert "downloading" in states
|
||||
|
||||
def test_final_size_update_syncs_transferred_to_size(self, tmp_path):
|
||||
"""size == transferred after success so monitor bytes-incomplete guard doesn't block."""
|
||||
client, audio_data = self._setup(tmp_path, decryption_key=None)
|
||||
engine = MagicMock()
|
||||
client._engine = engine
|
||||
|
||||
result = client._download_sync("dl-001", "B09XYZ1234", "Artist - Track")
|
||||
|
||||
assert result is not None
|
||||
# Last update must set size == transferred (both equal the output file size)
|
||||
final_calls = [
|
||||
c[0][2] for c in engine.update_record.call_args_list
|
||||
if 'size' in c[0][2] and 'transferred' in c[0][2]
|
||||
and c[0][2]['size'] == c[0][2]['transferred']
|
||||
and c[0][2]['size'] > 0
|
||||
]
|
||||
assert final_calls, "Expected a final engine update with size == transferred > 0"
|
||||
|
||||
def test_clear_stream_skips_ffmpeg(self, tmp_path):
|
||||
client, audio_data = self._setup(tmp_path, decryption_key=None)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue