feat: cleanup old binary versions after update#3255
feat: cleanup old binary versions after update#3255kristinemejia443-netizen wants to merge 1 commit into
Conversation
After a successful binary download, delete all previously downloaded version directories from the binary folder, keeping only the current version. Cleanup also runs on startup for each binary that already has its current version installed. Closes tari-project#3028 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request introduces a cleanup mechanism for old binary versions within the BinaryManager and BinaryResolver. While the logic correctly identifies and removes unused directories, the feedback highlights several critical improvements: error handling should be 'best-effort' to prevent cleanup failures from interrupting the main download process or batch operations, and synchronous file system calls should be replaced with asynchronous ones to avoid blocking the Tokio runtime.
| for (_binary, manager) in &self.managers { | ||
| manager.cleanup_old_versions().await?; | ||
| } |
There was a problem hiding this comment.
The cleanup process should be "best-effort" for all managed binaries. Using ? inside the loop causes the entire operation to stop if a single binary manager encounters an error during cleanup, preventing subsequent binaries from being processed. This contradicts the goal of not letting cleanup errors prevent normal operation.
for (binary, manager) in &self.managers {
let _unused = manager.cleanup_old_versions().await.inspect_err(|e| {
log::warn!(target: LOG_TARGET_APP_LOGIC, "Failed to cleanup old versions for {}: {e}", binary.name());
});
}References
- It is acceptable to implement workarounds to prevent errors in fragile downstream components, even if a more robust fix in the component itself is possible.
| let entries = std::fs::read_dir(&binary_folder)?; | ||
| for entry in entries.flatten() { | ||
| let path = entry.path(); | ||
| if path.is_dir() { | ||
| if let Some(dir_name) = path.file_name().and_then(|n| n.to_str()) { | ||
| if dir_name != self.selected_version { | ||
| info!(target: LOG_TARGET_APP_LOGIC, "Cleaning up old binary version: {path:?}"); | ||
| if let Err(e) = std::fs::remove_dir_all(&path) { | ||
| warn!(target: LOG_TARGET_APP_LOGIC, "Failed to remove old version directory {path:?}: {e}"); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
This method uses synchronous I/O (std::fs::read_dir and std::fs::remove_dir_all) inside an async fn. Since cleanup involves iterating over directories and potentially performing recursive deletions of large binary folders, this can block the Tokio worker thread for a significant amount of time. This can lead to performance degradation or UI unresponsiveness in a Tauri application. Consider using tokio::fs for non-blocking file operations.
Summary
Changes
binaries_manager.rs: Addedcleanup_old_versions()method that iterates the binary folder and removes all version subdirectories except the current one. Called after each successful download.binaries_resolver.rs: Addedcleanup_old_versions()that calls cleanup on all managed binaries. Wired intoinitialize_binary()so cleanup runs on startup even when no download is needed.Acceptance Criteria (from #3028)
Closes #3028
🤖 Generated with Claude Code