feat(core): improve troubleshooter behavior on critical errors
This commit is contained in:
parent
6dc3f1093d
commit
925a411460
|
@ -90,20 +90,26 @@ fn daemon_main(args: CliModuleArgs) -> i32 {
|
|||
// at a given time.
|
||||
let mut _current_troubleshoot_guard = None;
|
||||
|
||||
let config_store = match troubleshoot::load_config_or_troubleshoot(&paths, &paths_overrides) {
|
||||
troubleshoot::LoadResult::Correct(load_result) => load_result.config_store,
|
||||
troubleshoot::LoadResult::Warning(load_result, guard) => {
|
||||
_current_troubleshoot_guard = guard;
|
||||
load_result.config_store
|
||||
}
|
||||
troubleshoot::LoadResult::Fatal(mut guard) => {
|
||||
guard
|
||||
.wait()
|
||||
.expect("unable to wait for troubleshooting guard");
|
||||
error!("critical error while loading config");
|
||||
return DAEMON_FATAL_CONFIG_ERROR;
|
||||
}
|
||||
};
|
||||
let (watcher_notify, watcher_signal) = unbounded::<()>();
|
||||
|
||||
watcher::initialize_and_spawn(&paths.config, watcher_notify)
|
||||
.expect("unable to initialize config watcher thread");
|
||||
|
||||
let config_store =
|
||||
match troubleshoot::load_config_or_troubleshoot_until_config_is_correct_or_abort(
|
||||
&paths,
|
||||
&paths_overrides,
|
||||
watcher_signal.clone(),
|
||||
) {
|
||||
Ok((result, guard)) => {
|
||||
_current_troubleshoot_guard = guard;
|
||||
result.config_store
|
||||
}
|
||||
Err(err) => {
|
||||
error!("critical error while loading config: {}", err);
|
||||
return DAEMON_FATAL_CONFIG_ERROR;
|
||||
}
|
||||
};
|
||||
|
||||
info!("espanso version: {}", VERSION);
|
||||
// TODO: print os system and version? (with os_info crate)
|
||||
|
@ -126,13 +132,6 @@ fn daemon_main(args: CliModuleArgs) -> i32 {
|
|||
ipc::initialize_and_spawn(&paths.runtime, exit_notify.clone())
|
||||
.expect("unable to initialize ipc server for daemon");
|
||||
|
||||
let (watcher_notify, watcher_signal) = unbounded::<()>();
|
||||
|
||||
if config_store.default().auto_restart() {
|
||||
watcher::initialize_and_spawn(&paths.config, watcher_notify)
|
||||
.expect("unable to initialize config watcher thread");
|
||||
}
|
||||
|
||||
if cli_args.is_present("show-welcome") {
|
||||
ui::show_welcome_screen(&preferences);
|
||||
}
|
||||
|
@ -140,6 +139,10 @@ fn daemon_main(args: CliModuleArgs) -> i32 {
|
|||
loop {
|
||||
select! {
|
||||
recv(watcher_signal) -> _ => {
|
||||
if !config_store.default().auto_restart() {
|
||||
continue;
|
||||
}
|
||||
|
||||
info!("configuration change detected, restarting worker process...");
|
||||
|
||||
// Before killing the previous worker, we make sure there is no fatal error
|
||||
|
|
|
@ -18,9 +18,13 @@
|
|||
*/
|
||||
|
||||
use std::process::{Child, Command};
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Result};
|
||||
use anyhow::{bail, Result};
|
||||
use crossbeam::channel::Receiver;
|
||||
use crossbeam::select;
|
||||
use espanso_path::Paths;
|
||||
use log::info;
|
||||
|
||||
use crate::cli::util::CommandExt;
|
||||
use crate::cli::PathsOverrides;
|
||||
|
@ -47,10 +51,15 @@ impl TroubleshootGuard {
|
|||
pub fn new(child: Child) -> Self {
|
||||
Self { child }
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
pub fn wait(&mut self) -> Result<()> {
|
||||
self.child.wait()?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn try_wait(&mut self) -> Result<bool> {
|
||||
let result = self.child.try_wait()?;
|
||||
Ok(result.is_some())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TroubleshootGuard {
|
||||
|
@ -97,3 +106,44 @@ pub fn load_config_or_troubleshoot(paths: &Paths, paths_overrides: &PathsOverrid
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_config_or_troubleshoot_until_config_is_correct_or_abort(
|
||||
paths: &Paths,
|
||||
paths_overrides: &PathsOverrides,
|
||||
watcher_receiver: Receiver<()>,
|
||||
) -> Result<(ConfigLoadResult, Option<TroubleshootGuard>)> {
|
||||
let mut _troubleshoot_guard = None;
|
||||
|
||||
loop {
|
||||
// If the loading process is fatal, we keep showing the troubleshooter until
|
||||
// either the config is correct or the user aborts by closing the troubleshooter
|
||||
_troubleshoot_guard = match load_config_or_troubleshoot(paths, paths_overrides) {
|
||||
LoadResult::Correct(result) => return Ok((result, None)),
|
||||
LoadResult::Warning(result, guard) => return Ok((result, guard)),
|
||||
LoadResult::Fatal(guard) => Some(guard),
|
||||
};
|
||||
|
||||
loop {
|
||||
select! {
|
||||
recv(watcher_receiver) -> _ => {
|
||||
info!("config change detected, reloading configs...");
|
||||
|
||||
break
|
||||
},
|
||||
default(Duration::from_millis(500)) => {
|
||||
if let Some(guard) = &mut _troubleshoot_guard {
|
||||
if let Ok(ended) = guard.try_wait() {
|
||||
if ended {
|
||||
bail!("user aborted troubleshooter");
|
||||
}
|
||||
} else {
|
||||
bail!("unable to wait for troubleshooter");
|
||||
}
|
||||
} else {
|
||||
bail!("no troubleshoot guard found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user