remote: Add configurable remote server cache retention (default 5) (#47202)

Release Notes:

- Zed now removes older cached remote server downloads

---------

Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com>
This commit is contained in:
Xiaobo Liu 2026-01-26 15:25:51 +08:00 committed by GitHub
parent 9d7b6596dc
commit b397bd049a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 73 additions and 1 deletions

1
Cargo.lock generated
View file

@ -1350,6 +1350,7 @@ dependencies = [
"ctor",
"db",
"futures 0.3.31",
"futures-lite 1.13.0",
"gpui",
"http_client",
"log",

View file

@ -16,6 +16,7 @@ doctest = false
anyhow.workspace = true
client.workspace = true
db.workspace = true
futures-lite.workspace = true
gpui.workspace = true
http_client.workspace = true
log.workspace = true

View file

@ -1,6 +1,7 @@
use anyhow::{Context as _, Result};
use client::Client;
use db::kvp::KEY_VALUE_STORE;
use futures_lite::StreamExt;
use gpui::{
App, AppContext as _, AsyncApp, BackgroundExecutor, Context, Entity, Global, Task, Window,
actions,
@ -19,16 +20,18 @@ use std::{
self,
consts::{ARCH, OS},
},
ffi::OsStr,
ffi::OsString,
path::{Path, PathBuf},
sync::Arc,
time::Duration,
time::{Duration, SystemTime},
};
use util::command::new_smol_command;
use workspace::Workspace;
const SHOULD_SHOW_UPDATE_NOTIFICATION_KEY: &str = "auto-updater-should-show-updated-notification";
const POLL_INTERVAL: Duration = Duration::from_secs(60 * 60);
const REMOTE_SERVER_CACHE_LIMIT: usize = 5;
actions!(
auto_update,
@ -467,6 +470,16 @@ impl AutoUpdater {
download_remote_server_binary(&version_path, release, client).await?;
}
if let Err(error) =
cleanup_remote_server_cache(&platform_dir, &version_path, REMOTE_SERVER_CACHE_LIMIT)
.await
{
log::warn!(
"Failed to clean up remote server cache in {:?}: {error:#}",
platform_dir
);
}
Ok(version_path)
}
@ -785,6 +798,63 @@ async fn download_remote_server_binary(
Ok(())
}
async fn cleanup_remote_server_cache(
platform_dir: &Path,
keep_path: &Path,
limit: usize,
) -> Result<()> {
if limit == 0 {
return Ok(());
}
let mut entries = smol::fs::read_dir(platform_dir).await?;
let now = SystemTime::now();
let mut candidates = Vec::new();
while let Some(entry) = entries.next().await {
let entry = entry?;
let path = entry.path();
if path.extension() != Some(OsStr::new("gz")) {
continue;
}
let mtime = if path == keep_path {
now
} else {
smol::fs::metadata(&path)
.await
.and_then(|metadata| metadata.modified())
.unwrap_or(SystemTime::UNIX_EPOCH)
};
candidates.push((path, mtime));
}
if candidates.len() <= limit {
return Ok(());
}
candidates.sort_by(|(path_a, time_a), (path_b, time_b)| {
time_b.cmp(time_a).then_with(|| path_a.cmp(path_b))
});
for (index, (path, _)) in candidates.into_iter().enumerate() {
if index < limit || path == keep_path {
continue;
}
if let Err(error) = smol::fs::remove_file(&path).await {
log::warn!(
"Failed to remove old remote server archive {:?}: {}",
path,
error
);
}
}
Ok(())
}
async fn download_release(
target_path: &Path,
release: ReleaseAsset,