feat: allow cancelling stalled downloads - #525
Conversation
34d749f to
ff77e20
Compare
7b5418f to
cb1523a
Compare
Verdict: Worth addingYes. A progress callback cannot run while a read is blocked, so stopping a stalled read is a capability callers do not have today, and osam#100 needs it. The feature is opt-in: with Correctness
MinimalityThe polling reader and the three nested classes are justified: they are the only way to reach the header read through requests. Optional trims:
TestsMeaningful and integrated: they go through the public API against real local HTTP, HTTPS, HTTP-proxy, and SOCKS5 servers. The patched seams are backoff length, Mutation check: 13 of 17 mutants killed. Survivors:
Nit: Not verifiedWindows behaviour (relied on CI), the urllib3 1.26.20 and 2.0.7 claim, HTTPS through an HTTPS proxy, and pyOpenSSL-injected sockets. The 8 commits include fixups of code that never shipped; consider squashing or reshaping history at merge. |
Accept a caller-owned event to stop response reads and download waits without shortening network timeouts. Preserve partial-file cleanup and raise DownloadCancelled separately from download failures. Use cancellable buffered reads across HTTP, HTTPS, and proxy connections. Cover timeout preservation, publication boundaries, and cancellation cleanup with local-server tests, and record the API decision.
da3c353 to
474f4d4
Compare
Applications need to cancel a stalled download before its network timeout expires. Progress callbacks cannot run while a read is blocked, and lowering the timeout rejects slow but valid transfers.
Closes #524. Provides the upstream support for wkentaro/osam#100.
The reader polls socket readiness while preserving the original timeout. Cross-thread shutdown did not wake stalled direct reads on Windows, and short socket timeouts poison buffered reads; keeping cancellation inside the read avoids both problems. This relies on urllib3 connection pools and the standard-library response class, which is the main maintenance cost.
Prompt interruption covers response headers, bodies, retry backoff, and speed-limit waits. DNS/connect/TLS setup, proxy negotiation, filesystem operations, and caller callbacks remain outside that guarantee. HTTPS-through-HTTPS-proxy and pyOpenSSL-injected sockets have not been verified.
Validation:
just lintand 217 non-network tests pass in an isolated worktree at the final commit. All 46 cancellation tests were also verified with urllib3 1.26.20 and 2.0.7. Local-server tests cover stalled reads, timeout preservation, redirects/reconnects, HTTP/SOCKS proxies, cleanup, concurrent isolation, and publication boundaries. Mutation checks verify the proxy-body tests and cache guards and show why the retry and per-chunk guards are needed.Separate media is omitted because the timed local-server tests directly demonstrate cancellation before the network timeout.