|
|
|
|
@@ -21,7 +21,7 @@ use crate::constants::VSCODE_CLI_QUALITY;
|
|
|
|
|
use crate::download_cache::DownloadCache;
|
|
|
|
|
use crate::log;
|
|
|
|
|
use crate::options::Quality;
|
|
|
|
|
use crate::tunnels::paths::SERVER_FOLDER_NAME;
|
|
|
|
|
use crate::tunnels::paths::{get_server_folder_name, SERVER_FOLDER_NAME};
|
|
|
|
|
use crate::tunnels::shutdown_signal::ShutdownRequest;
|
|
|
|
|
use crate::update_service::{
|
|
|
|
|
unzip_downloaded_release, Platform, Release, TargetKind, UpdateService,
|
|
|
|
|
@@ -74,8 +74,13 @@ pub async fn agent_host(ctx: CommandContext, mut args: AgentHostArgs) -> Result<
|
|
|
|
|
// Eagerly resolve the latest version so the first connection is fast.
|
|
|
|
|
// Skip when using a dev override since updates don't apply.
|
|
|
|
|
if option_env!("VSCODE_CLI_OVERRIDE_SERVER_PATH").is_none() {
|
|
|
|
|
if let Err(e) = manager.get_latest_release().await {
|
|
|
|
|
warning!(ctx.log, "Error resolving initial server version: {}", e);
|
|
|
|
|
match manager.get_latest_release().await {
|
|
|
|
|
Ok(release) => {
|
|
|
|
|
if let Err(e) = manager.ensure_downloaded(&release).await {
|
|
|
|
|
warning!(ctx.log, "Error downloading latest server version: {}", e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Err(e) => warning!(ctx.log, "Error resolving initial server version: {}", e),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Start background update checker
|
|
|
|
|
@@ -253,9 +258,12 @@ impl AgentHostManager {
|
|
|
|
|
cmd.stdin(std::process::Stdio::null());
|
|
|
|
|
cmd.stderr(std::process::Stdio::piped());
|
|
|
|
|
cmd.stdout(std::process::Stdio::piped());
|
|
|
|
|
cmd.arg("--socket-path");
|
|
|
|
|
cmd.arg(get_socket_name());
|
|
|
|
|
cmd.arg("--agent-host-path");
|
|
|
|
|
cmd.arg(&agent_host_socket);
|
|
|
|
|
cmd.args([
|
|
|
|
|
"--start-server",
|
|
|
|
|
"--accept-server-license-terms",
|
|
|
|
|
"--enable-remote-auto-shutdown",
|
|
|
|
|
]);
|
|
|
|
|
@@ -394,7 +402,8 @@ impl AgentHostManager {
|
|
|
|
|
|
|
|
|
|
// Best case: the latest known release is already downloaded
|
|
|
|
|
if let Some((_, release)) = &*self.latest_release.lock().await {
|
|
|
|
|
if let Some(dir) = self.cache.exists(&release.commit) {
|
|
|
|
|
let name = get_server_folder_name(release.quality, &release.commit);
|
|
|
|
|
if let Some(dir) = self.cache.exists(&name) {
|
|
|
|
|
return Ok((release.clone(), dir));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -405,15 +414,23 @@ impl AgentHostManager {
|
|
|
|
|
Quality::try_from(q).map_err(|_| CodeError::UpdatesNotConfigured("unknown quality"))
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
// Fall back to any cached version (still instant, just not the newest)
|
|
|
|
|
for commit in self.cache.get() {
|
|
|
|
|
if let Some(dir) = self.cache.exists(&commit) {
|
|
|
|
|
// Fall back to any cached version (still instant, just not the newest).
|
|
|
|
|
// Cache entries are named "<quality>-<commit>" via get_server_folder_name.
|
|
|
|
|
for entry in self.cache.get() {
|
|
|
|
|
if let Some(dir) = self.cache.exists(&entry) {
|
|
|
|
|
let (entry_quality, commit) = match entry.split_once('-') {
|
|
|
|
|
Some((q, c)) => match Quality::try_from(q.to_lowercase().as_str()) {
|
|
|
|
|
Ok(parsed) => (parsed, c.to_string()),
|
|
|
|
|
Err(_) => (quality, entry.clone()),
|
|
|
|
|
},
|
|
|
|
|
None => (quality, entry.clone()),
|
|
|
|
|
};
|
|
|
|
|
let release = Release {
|
|
|
|
|
name: String::new(),
|
|
|
|
|
commit,
|
|
|
|
|
platform: self.platform,
|
|
|
|
|
target: TargetKind::Server,
|
|
|
|
|
quality,
|
|
|
|
|
quality: entry_quality,
|
|
|
|
|
};
|
|
|
|
|
return Ok((release, dir));
|
|
|
|
|
}
|
|
|
|
|
@@ -428,7 +445,8 @@ impl AgentHostManager {
|
|
|
|
|
|
|
|
|
|
/// Ensures the release is downloaded, returning the server directory.
|
|
|
|
|
async fn ensure_downloaded(&self, release: &Release) -> Result<PathBuf, CodeError> {
|
|
|
|
|
if let Some(dir) = self.cache.exists(&release.commit) {
|
|
|
|
|
let cache_name = get_server_folder_name(release.quality, &release.commit);
|
|
|
|
|
if let Some(dir) = self.cache.exists(&cache_name) {
|
|
|
|
|
return Ok(dir);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -436,9 +454,8 @@ impl AgentHostManager {
|
|
|
|
|
let release = release.clone();
|
|
|
|
|
let log = self.log.clone();
|
|
|
|
|
let update_service = self.update_service.clone();
|
|
|
|
|
let commit = release.commit.clone();
|
|
|
|
|
self.cache
|
|
|
|
|
.create(&commit, |target_dir| async move {
|
|
|
|
|
.create(&cache_name, |target_dir| async move {
|
|
|
|
|
let tmpdir = tempfile::tempdir().unwrap();
|
|
|
|
|
let response = update_service.get_download_stream(&release).await?;
|
|
|
|
|
let name = response.url_path_basename().unwrap();
|
|
|
|
|
@@ -449,7 +466,8 @@ impl AgentHostManager {
|
|
|
|
|
response,
|
|
|
|
|
)
|
|
|
|
|
.await?;
|
|
|
|
|
unzip_downloaded_release(&archive_path, &target_dir, SilentCopyProgress())?;
|
|
|
|
|
let server_dir = target_dir.join(SERVER_FOLDER_NAME);
|
|
|
|
|
unzip_downloaded_release(&archive_path, &server_dir, SilentCopyProgress())?;
|
|
|
|
|
Ok(())
|
|
|
|
|
})
|
|
|
|
|
.await
|
|
|
|
|
@@ -504,7 +522,8 @@ impl AgentHostManager {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Check if we already have this version
|
|
|
|
|
if self.cache.exists(&new_release.commit).is_some() {
|
|
|
|
|
let name = get_server_folder_name(new_release.quality, &new_release.commit);
|
|
|
|
|
if self.cache.exists(&name).is_some() {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -562,7 +581,10 @@ async fn handle_request(
|
|
|
|
|
let rw = match get_socket_rw_stream(&socket_path).await {
|
|
|
|
|
Ok(rw) => rw,
|
|
|
|
|
Err(e) => {
|
|
|
|
|
error!(manager.log, "Error connecting to agent host socket: {:?}", e);
|
|
|
|
|
error!(
|
|
|
|
|
manager.log,
|
|
|
|
|
"Error connecting to agent host socket: {:?}", e
|
|
|
|
|
);
|
|
|
|
|
return Ok(Response::builder()
|
|
|
|
|
.status(503)
|
|
|
|
|
.body(Body::from(format!("Error connecting to agent host: {e:?}")))
|
|
|
|
|
|