diff --git a/crates/turborepo-lib/src/commands/daemon.rs b/crates/turborepo-lib/src/commands/daemon.rs index 7c06a4f7d3b3c..37a07104ceca5 100644 --- a/crates/turborepo-lib/src/commands/daemon.rs +++ b/crates/turborepo-lib/src/commands/daemon.rs @@ -6,7 +6,7 @@ use pidlock::PidlockError::AlreadyOwned; use time::{format_description, OffsetDateTime}; use tokio::signal::ctrl_c; use tracing::{trace, warn}; -use turbopath::AbsoluteSystemPathBuf; +use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; use super::CommandBase; use crate::{ @@ -19,8 +19,8 @@ use crate::{ pub async fn daemon_client(command: &DaemonCommand, base: &CommandBase) -> Result<(), DaemonError> { let (can_start_server, can_kill_server) = match command { DaemonCommand::Status { .. } => (false, false), - DaemonCommand::Restart | DaemonCommand::Stop => (false, true), - DaemonCommand::Start => (true, true), + DaemonCommand::Stop => (false, true), + DaemonCommand::Restart | DaemonCommand::Start => (true, true), DaemonCommand::Clean => (false, true), }; @@ -36,8 +36,20 @@ pub async fn daemon_client(command: &DaemonCommand, base: &CommandBase) -> Resul match command { DaemonCommand::Restart => { - let client = connector.connect().await?; - client.restart().await?; + let result: Result<_, DaemonError> = try { + let client = connector.clone().connect().await?; + client.restart().await? + }; + + if let Err(e) = result { + tracing::debug!("failed to restart the daemon: {:?}", e); + tracing::debug!("falling back to clean"); + clean(&pid_file, &sock_file).await?; + tracing::debug!("connecting for second time"); + let _ = connector.connect().await?; + } + + println!("restarted daemon"); } DaemonCommand::Start => { // We don't care about the client, but we do care that we can connect @@ -87,42 +99,49 @@ pub async fn daemon_client(command: &DaemonCommand, base: &CommandBase) -> Resul tracing::trace!("unable to connect to the daemon: {:?}", e); } } - - // remove pid and sock files - let mut success = true; - trace!("cleaning up daemon files"); - // if the pid_file and sock_file still exist, remove them: - if pid_file.exists() { - let result = std::fs::remove_file(pid_file.clone()); - // ignore this error - if let Err(e) = result { - println!("Failed to remove pid file: {}", e); - println!("Please remove manually: {}", pid_file); - success = false; - } - } - if sock_file.exists() { - let result = std::fs::remove_file(sock_file.clone()); - // ignore this error - if let Err(e) = result { - println!("Failed to remove socket file: {}", e); - println!("Please remove manually: {}", sock_file); - success = false; - } - } - - if success { - println!("Done"); - } else { - // return error - return Err(DaemonError::CleanFailed); - } + clean(&pid_file, &sock_file).await?; + println!("Done"); } }; Ok(()) } +async fn clean( + pid_file: &AbsoluteSystemPath, + sock_file: &AbsoluteSystemPath, +) -> Result<(), DaemonError> { + // remove pid and sock files + let mut success = true; + trace!("cleaning up daemon files"); + // if the pid_file and sock_file still exist, remove them: + if pid_file.exists() { + let result = std::fs::remove_file(pid_file); + // ignore this error + if let Err(e) = result { + println!("Failed to remove pid file: {}", e); + println!("Please remove manually: {}", pid_file); + success = false; + } + } + if sock_file.exists() { + let result = std::fs::remove_file(sock_file); + // ignore this error + if let Err(e) = result { + println!("Failed to remove socket file: {}", e); + println!("Please remove manually: {}", sock_file); + success = false; + } + } + + if success { + Ok(()) + } else { + // return error + Err(DaemonError::CleanFailed) + } +} + // log_filename matches the algorithm used by tracing_appender::Rotation::DAILY // to generate the log filename. This is kind of a hack, but there didn't appear // to be a simple way to grab the generated filename. diff --git a/crates/turborepo-lib/src/lib.rs b/crates/turborepo-lib/src/lib.rs index 8a4c3b3f91bc3..54eb888197398 100644 --- a/crates/turborepo-lib/src/lib.rs +++ b/crates/turborepo-lib/src/lib.rs @@ -5,6 +5,7 @@ #![feature(hash_extract_if)] #![feature(option_get_or_insert_default)] #![feature(once_cell_try)] +#![feature(try_blocks)] #![deny(clippy::all)] // Clippy's needless mut lint is buggy: https://github.com/rust-lang/rust-clippy/issues/11299 #![allow(clippy::needless_pass_by_ref_mut)]