feat: improved error display when startup fails

This commit is contained in:
Paul Campbell 2024-09-01 13:10:14 +01:00
parent 4160b6d6ee
commit 3c01a822fd
3 changed files with 61 additions and 32 deletions

View file

@ -3,16 +3,17 @@ use actix::prelude::*;
use actix::Recipient; use actix::Recipient;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use notify::event::ModifyKind; use notify::{event::ModifyKind, Watcher};
use notify::Watcher; use tracing::{error, info};
use tracing::error;
use tracing::info;
use std::path::PathBuf; use std::{
use std::sync::atomic::AtomicBool; path::PathBuf,
use std::sync::atomic::Ordering; sync::{
use std::sync::Arc; atomic::{AtomicBool, Ordering},
use std::time::Duration; Arc,
},
time::Duration,
};
#[derive(Debug, Message)] #[derive(Debug, Message)]
#[rtype(result = "()")] #[rtype(result = "()")]
@ -30,8 +31,7 @@ pub fn watch_file(path: PathBuf, recipient: Recipient<FileUpdated>) -> Result<Ar
let mut handler = notify::recommended_watcher(tx).context("file watcher")?; let mut handler = notify::recommended_watcher(tx).context("file watcher")?;
handler handler
.watch(&path, notify::RecursiveMode::NonRecursive) .watch(&path, notify::RecursiveMode::NonRecursive)
.with_context(|| format!("Watch file: {path:?}"))?; .with_context(|| format!("Watching: {path:?}"))?;
info!("Watching: {:?}", path);
let thread_shutdown = shutdown.clone(); let thread_shutdown = shutdown.clone();
actix_rt::task::spawn_blocking(move || { actix_rt::task::spawn_blocking(move || {
loop { loop {
@ -43,7 +43,7 @@ pub fn watch_file(path: PathBuf, recipient: Recipient<FileUpdated>) -> Result<Ar
match result { match result {
Ok(event) => match event.kind { Ok(event) => match event.kind {
notify::EventKind::Modify(ModifyKind::Data(_)) => { notify::EventKind::Modify(ModifyKind::Data(_)) => {
tracing::info!("File modified"); info!("File modified");
recipient.do_send(FileUpdated); recipient.do_send(FileUpdated);
break; break;
} }

View file

@ -53,24 +53,25 @@ fn main() -> Result<()> {
let commands = Commands::parse(); let commands = Commands::parse();
match commands.command { match commands.command {
Command::Init => { Command::Init => init::run(&fs),
init::run(&fs)?;
}
Command::Server(server) => match server { Command::Server(server) => match server {
Server::Init => { Server::Init => server::init(&fs),
server::init(&fs)?;
}
#[cfg(not(feature = "tui"))] #[cfg(not(feature = "tui"))]
Server::Start {} => { Server::Start {} => server::start(
let sleep_duration = std::time::Duration::from_secs(10); false,
server::start(false, fs, net, repository_factory, sleep_duration)?; fs,
} net,
repository_factory,
std::time::Duration::from_secs(10),
),
#[cfg(feature = "tui")] #[cfg(feature = "tui")]
Server::Start { ui } => { Server::Start { ui } => server::start(
let sleep_duration = std::time::Duration::from_secs(10); ui,
server::start(ui, fs, net, repository_factory, sleep_duration)?; fs,
} net,
repository_factory,
std::time::Duration::from_secs(10),
),
}, },
} }
Ok(())
} }

View file

@ -19,9 +19,13 @@ use git_next_core::git::RepositoryFactory;
use color_eyre::{eyre::Context, Result}; use color_eyre::{eyre::Context, Result};
use kxio::{fs::FileSystem, network::Network}; use kxio::{fs::FileSystem, network::Network};
use tracing::info; use tracing::{error, info};
use std::{path::PathBuf, sync::atomic::Ordering, time::Duration}; use std::{
path::PathBuf,
sync::{atomic::Ordering, Arc, RwLock},
time::Duration,
};
const A_DAY: Duration = Duration::from_secs(24 * 60 * 60); const A_DAY: Duration = Duration::from_secs(24 * 60 * 60);
@ -57,6 +61,8 @@ pub fn start(
init_logging(); init_logging();
} }
let file_watcher_err_channel: Arc<RwLock<Option<anyhow::Error>>> = Arc::new(RwLock::new(None));
let file_watcher_err_channel_exec = file_watcher_err_channel.clone();
let execution = async move { let execution = async move {
info!("Starting Alert Dispatcher..."); info!("Starting Alert Dispatcher...");
let alerts_addr = AlertsActor::new(None, History::new(A_DAY), net.clone()).start(); let alerts_addr = AlertsActor::new(None, History::new(A_DAY), net.clone()).start();
@ -66,9 +72,20 @@ pub fn start(
ServerActor::new(fs.clone(), net.clone(), alerts_addr, repo, sleep_duration).start(); ServerActor::new(fs.clone(), net.clone(), alerts_addr, repo, sleep_duration).start();
info!("Starting File Watcher..."); info!("Starting File Watcher...");
#[allow(clippy::expect_used)] let watch_file = watch_file("git-next-server.toml".into(), server.clone().recipient());
let fw_shutdown = watch_file("git-next-server.toml".into(), server.clone().recipient()) let fw_shutdown = match watch_file {
.expect("file watcher"); Ok(fw_shutdown) => fw_shutdown,
Err(err) => {
// shutdown now
server.do_send(crate::server::actor::messages::Shutdown);
actix_rt::time::sleep(std::time::Duration::from_millis(10)).await;
System::current().stop();
let _ = file_watcher_err_channel_exec
.write()
.map(|mut o| o.replace(err));
return;
}
};
if ui { if ui {
#[cfg(feature = "tui")] #[cfg(feature = "tui")]
@ -106,6 +123,17 @@ pub fn start(
let system = System::new(); let system = System::new();
Arbiter::current().spawn(execution); Arbiter::current().spawn(execution);
system.run()?; system.run()?;
// check for error from file watcher thread
#[allow(clippy::unwrap_used)]
if let Some(err) = &*file_watcher_err_channel.read().unwrap() {
if ui {
eprintln!("File Watcher: {err:?}");
}
error!(?err, "file watcher");
return Err(color_eyre::eyre::eyre!(format!("{err}")));
}
Ok(()) Ok(())
} }