From 7ba29eeb3beda73b763dcfb857f668a1a125192f Mon Sep 17 00:00:00 2001 From: pawank925 <229111348+pawank925@users.noreply.github.com> Date: Wed, 14 Oct 2026 11:10:44 +0530 Subject: [PATCH] Make save_large_file resumable with progress-based retries save_large_file() shelled out to a single wget run with -t {retries}. wget's -t is a budget for the whole download, not for consecutive failures: a connection that drops every few hundred MB exhausts it and aborts with no further retry, even though every attempt resumes correctly. That is what made long downloads fail in production (see openzim/zimwright#3). Stream the response with requests instead, deriving the resume point from the bytes already on disk and sending a Range request. The retry counter now only grows on attempts that make no progress at all: any attempt that writes at least one byte resets it, so a flaky-but-advancing download keeps resuming until it completes. Transient HTTP statuses (matching the existing requests retry adapter) and connection/timeout/chunked-encoding errors are retried with exponential backoff; anything else raises the new DownloadError. If the server ignores the Range request, the file is started over. This is the same approach already used by zimwright, which can now rely on the library implementation. Closes #348. --- CHANGELOG.md | 1 + src/zimscraperlib/download.py | 103 +++++++++++++------ tests/download/test_download.py | 175 +++++++++++++++++++++++++++++++- 3 files changed, 247 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1de7b951..018c058e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Rewrite `save_large_file` to stream and resume the download itself instead of running `wget` once, whose `-t` counter is a budget for the whole download: a flaky connection now keeps resuming and the retry budget only counts attempts that make no progress, so long downloads are no longer abandoned mid-way (#348) - Carry a script's top-level `const`, `let` and `class` declarations across the wombat block, so other scripts on the page can still see them (#329) - Keep a rewritten `