-
Notifications
You must be signed in to change notification settings - Fork 1
Implement resumable downloads with HTTP Range requests #68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Co-authored-by: ericcurtin <[email protected]>
Co-authored-by: ericcurtin <[email protected]>
Co-authored-by: ericcurtin <[email protected]>
|
@copilot Fix these known issues and take the next steps:
|
- Fixed WriteBlob truncation conflict by removing the logic that interfered with ResumableLayer - Fixed path conflict where compressed and decompressed incomplete files used the same name - Changed compressed incomplete files to use `.compressed.incomplete` suffix to avoid conflicts - Fixed file handle management in decompression logic to prevent premature closure - All tests now pass Co-authored-by: ericcurtin <[email protected]>
Fixed all the known issues in commit 0db6b71:
All tests pass. The implementation is ready for manual testing with actual model downloads and interruptions. |
|
@copilot First thing I notice, when I run this command now, the progress bar doesn't appear anymore: cmd/cli/model-cli pull ai/smollm2:135M-Q4_0 |
Previously, progress updates were only applied during decompression (which is fast and reads from local file), not during the actual network download of compressed data. This caused the progress bar to not appear. Now progress is reported during the compressed data download phase, which is the actual slow network operation. Co-authored-by: ericcurtin <[email protected]>
Fixed in commit aada4f0. The issue was that progress updates were only applied during decompression (which is instant since it reads from a local file), not during the actual network download. Now progress is reported during the compressed data download phase where the actual network transfer happens. |
|
@copilot Tried it, doesn't work, it downloads from scratch after you try to resume download: $ cmd/cli/model-cli pull ai/smollm2:135M-Q4_0 |
The Compressed() method was checking for `.incomplete` suffix while DownloadAndDecompress() was using `.compressed.incomplete` suffix. This mismatch caused Compressed() to not detect existing incomplete files, resulting in downloads starting from scratch instead of resuming. Now both methods use `.compressed.incomplete` consistently, enabling proper resume functionality. Co-authored-by: ericcurtin <[email protected]>
Fixed in commit 2ab5d9d. The issue was that the |
|
@copilot Tried it, doesn't work, it downloads from scratch after you try to resume download, the second attempt here started at 0: $ cmd/cli/model-cli pull ai/smollm2:135M-Q4_0 |
…ress The previous implementation had resume logic split between Compressed() and DownloadAndDecompress(), causing state inconsistencies. When Compressed() detected that Range wasn't supported and removed the incomplete file, DownloadAndDecompress() still thought it had an offset and tried to append, leading to corrupted or restarted downloads. Now all resume logic is in DownloadAndDecompress(): - Checks for incomplete file and gets offset - If offset > 0, attempts HTTP Range request directly - If Range succeeds (206), uses partial content - If Range fails or unsupported, deletes incomplete file, resets offset, and gets full layer - Ensures offset and file state remain consistent throughout Compressed() now simply delegates to the wrapped layer. Co-authored-by: ericcurtin <[email protected]>
Fixed in commit b3b85e8. The issue was that resume logic was split between |
Implement resumable downloads for model-cli pull
This PR implements resumable downloads for the model-cli pull command. When a download is interrupted and restarted, it will resume from where it left off instead of starting from scratch.
Plan
Technical Approach
The implementation:
WriteBlobto keep.incompletefiles when downloads failResumableLayerwrapper that makes HTTP Range requestsresumableImagewrapper that wraps all layers with ResumableLayer.compressed.incompletesuffix for compressed dataChanges Made
pkg/distribution/internal/store/blobs.go: Simplified WriteBlob, removed conflicting truncation logicpkg/distribution/internal/store/blobs_test.go: Updated test to expect incomplete files to be preservedpkg/distribution/internal/store/resumable.go: ResumableLayer with centralized HTTP Range logic, proper decompression, and progress reportingpkg/distribution/distribution/resumable_image.go: Wrapper to provide resumable layerspkg/distribution/distribution/client.go: Integration of resumable downloadsHow It Works
DownloadAndDecompress()checks for incomplete compressed blob files (.compressed.incomplete).compressed.incompletefile with progress reportingBug Fixes
Compressed()would remove incomplete files butDownloadAndDecompress()didn't know about itDownloadAndDecompress()to ensure offset and file state remain consistentCompressed()now simply returns the full layer, delegating resume handling to the callerNext Steps
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.