From 89975894a4745ea91ca426b8e1887df56627ef1b Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Tue, 30 Jul 2024 11:37:47 +0100 Subject: [PATCH] feat: terminate process if config file is invalid --- crates/cli/src/file_watcher.rs | 10 +++++----- .../cli/src/server/actor/handlers/file_updated.rs | 10 +++++----- .../server/actor/handlers/receive_server_config.rs | 9 +++------ crates/cli/src/server/actor/mod.rs | 13 +++++++++++++ crates/cli/src/server/mod.rs | 5 ++++- 5 files changed, 30 insertions(+), 17 deletions(-) diff --git a/crates/cli/src/file_watcher.rs b/crates/cli/src/file_watcher.rs index ca0156a..c6bfc3d 100644 --- a/crates/cli/src/file_watcher.rs +++ b/crates/cli/src/file_watcher.rs @@ -2,6 +2,7 @@ use actix::prelude::*; use actix::Recipient; +use anyhow::{Context, Result}; use notify::event::ModifyKind; use notify::Watcher; use tracing::error; @@ -19,15 +20,13 @@ pub enum Error { #[error("io")] Io(#[from] std::io::Error), } -pub async fn watch_file(path: PathBuf, recipient: Recipient) { +pub async fn watch_file(path: PathBuf, recipient: Recipient) -> Result<()> { let (tx, rx) = std::sync::mpsc::channel(); - #[allow(clippy::expect_used)] - let mut handler = notify::recommended_watcher(tx).expect("file watcher"); - #[allow(clippy::expect_used)] + let mut handler = notify::recommended_watcher(tx).context("file watcher")?; handler .watch(&path, notify::RecursiveMode::NonRecursive) - .expect("watch file"); + .with_context(|| format!("Watch file: {path:?}"))?; info!("Watching: {:?}", path); async move { loop { @@ -55,4 +54,5 @@ pub async fn watch_file(path: PathBuf, recipient: Recipient) { } } .await; + Ok(()) } diff --git a/crates/cli/src/server/actor/handlers/file_updated.rs b/crates/cli/src/server/actor/handlers/file_updated.rs index 7aa6d49..fb49d35 100644 --- a/crates/cli/src/server/actor/handlers/file_updated.rs +++ b/crates/cli/src/server/actor/handlers/file_updated.rs @@ -12,13 +12,13 @@ impl Handler for ServerActor { type Result = (); fn handle(&mut self, _msg: FileUpdated, ctx: &mut Self::Context) -> Self::Result { - let server_config = match ServerConfig::load(&self.fs) { - Ok(server_config) => server_config, + match ServerConfig::load(&self.fs) { + Ok(server_config) => { + self.do_send(ReceiveServerConfig::new(server_config), ctx); + } Err(err) => { - tracing::error!("Failed to load config file. Error: {}", err); - return; + self.abort(ctx, format!("Failed to load config file. Error: {}", err)); } }; - self.do_send(ReceiveServerConfig::new(server_config), ctx); } } diff --git a/crates/cli/src/server/actor/handlers/receive_server_config.rs b/crates/cli/src/server/actor/handlers/receive_server_config.rs index 889f5ed..121a4ae 100644 --- a/crates/cli/src/server/actor/handlers/receive_server_config.rs +++ b/crates/cli/src/server/actor/handlers/receive_server_config.rs @@ -12,18 +12,15 @@ impl Handler for ServerActor { fn handle(&mut self, msg: ReceiveServerConfig, ctx: &mut Self::Context) -> Self::Result { tracing::info!("recieved server config"); let Ok(socket_addr) = msg.http() else { - tracing::error!("Unable to parse http.addr"); - return; + self.abort(ctx, "Unable to parse http.addr"); }; let Some(server_storage) = self.server_storage(&msg) else { - tracing::error!("Server storage not available"); - return; + self.abort(ctx, "Server storage not available"); }; if msg.inbound_webhook().base_url().ends_with('/') { - tracing::error!("webhook.url must not end with a '/'"); - return; + self.abort(ctx, "webhook.url must not end with a '/'"); } self.do_send( diff --git a/crates/cli/src/server/actor/mod.rs b/crates/cli/src/server/actor/mod.rs index dd4e717..763d79e 100644 --- a/crates/cli/src/server/actor/mod.rs +++ b/crates/cli/src/server/actor/mod.rs @@ -229,6 +229,19 @@ impl ServerActor { Some(server_storage) } + /// Attempts to gracefully shutdown the server before terminating the process. + fn abort( + &mut self, + ctx: &mut ::Context, + message: impl Into, + ) -> ! { + tracing::error!("Aborting: {}", message.into()); + self.do_send(crate::server::actor::messages::Shutdown, ctx); + std::thread::sleep(std::time::Duration::from_millis(200)); + System::current().stop(); + std::process::exit(-1); + } + fn do_send(&mut self, msg: M, _ctx: &mut ::Context) where M: actix::Message + Send + 'static + std::fmt::Debug, diff --git a/crates/cli/src/server/mod.rs b/crates/cli/src/server/mod.rs index 2ec68d4..f2b9673 100644 --- a/crates/cli/src/server/mod.rs +++ b/crates/cli/src/server/mod.rs @@ -46,7 +46,10 @@ pub fn start( server.do_send(FileUpdated); info!("Starting File Watcher..."); - watch_file("git-next-server.toml".into(), server.clone().recipient()).await; + #[allow(clippy::expect_used)] + watch_file("git-next-server.toml".into(), server.clone().recipient()) + .await + .expect("file watcher"); info!("Server running - Press Ctrl-C to stop..."); let _ = actix_rt::signal::ctrl_c().await;