feat(core): implement run-count config in worker

This commit is contained in:
Federico Terzi 2021-07-21 20:23:37 +02:00
parent acf4286cd4
commit 2d559b7fb0
4 changed files with 65 additions and 21 deletions

View File

@ -50,6 +50,7 @@ pub fn new() -> CliModule {
#[allow(clippy::needless_update)] #[allow(clippy::needless_update)]
CliModule { CliModule {
requires_paths: true, requires_paths: true,
enable_logs: true,
log_mode: super::LogMode::CleanAndAppend, log_mode: super::LogMode::CleanAndAppend,
subcommand: "daemon".to_string(), subcommand: "daemon".to_string(),
entry: daemon_main, entry: daemon_main,
@ -102,7 +103,14 @@ fn daemon_main(args: CliModuleArgs) -> i32 {
// TODO: register signals to terminate the worker if the daemon terminates // TODO: register signals to terminate the worker if the daemon terminates
spawn_worker(&paths, &paths_overrides, exit_notify.clone()); let mut worker_run_count = 0;
spawn_worker(
&paths,
&paths_overrides,
exit_notify.clone(),
&mut worker_run_count,
);
ipc::initialize_and_spawn(&paths.runtime, exit_notify.clone()) ipc::initialize_and_spawn(&paths.runtime, exit_notify.clone())
.expect("unable to initialize ipc server for daemon"); .expect("unable to initialize ipc server for daemon");
@ -151,7 +159,7 @@ fn daemon_main(args: CliModuleArgs) -> i32 {
} }
if !has_timed_out { if !has_timed_out {
spawn_worker(&paths, &paths_overrides, exit_notify.clone()); spawn_worker(&paths, &paths_overrides, exit_notify.clone(), &mut worker_run_count);
} else { } else {
error!("could not restart worker, as the exit process has timed out"); error!("could not restart worker, as the exit process has timed out");
} }
@ -166,7 +174,7 @@ fn daemon_main(args: CliModuleArgs) -> i32 {
} }
WORKER_RESTART => { WORKER_RESTART => {
info!("worker requested a restart, spawning a new one..."); info!("worker requested a restart, spawning a new one...");
spawn_worker(&paths, &paths_overrides, exit_notify.clone()); spawn_worker(&paths, &paths_overrides, exit_notify.clone(), &mut worker_run_count);
} }
_ => { _ => {
error!("received unexpected exit code from worker {}, exiting", code); error!("received unexpected exit code from worker {}, exiting", code);
@ -223,17 +231,26 @@ fn terminate_worker_if_already_running(runtime_dir: &Path) {
) )
} }
fn spawn_worker(paths: &Paths, paths_overrides: &PathsOverrides, exit_notify: Sender<i32>) { fn spawn_worker(
paths: &Paths,
paths_overrides: &PathsOverrides,
exit_notify: Sender<i32>,
worker_run_count: &mut i32,
) {
info!("spawning the worker process..."); info!("spawning the worker process...");
let espanso_exe_path = let espanso_exe_path =
std::env::current_exe().expect("unable to obtain espanso executable location"); std::env::current_exe().expect("unable to obtain espanso executable location");
// Before starting the worker, check if the configuration has any error, and if so, show the troubleshooting GUI // Before starting the worker, check if the configuration has any error, and if so, show the troubleshooting GUI
let troubleshoot_guard = match troubleshoot::load_config_or_troubleshoot(paths, paths_overrides, true) { let troubleshoot_guard =
match troubleshoot::load_config_or_troubleshoot(paths, paths_overrides, true) {
Ok((_, troubleshoot_guard)) => troubleshoot_guard, Ok((_, troubleshoot_guard)) => troubleshoot_guard,
Err(fatal_err) => { Err(fatal_err) => {
error!("critical configuration error detected, unable to restart worker: {:?}", fatal_err); error!(
"critical configuration error detected, unable to restart worker: {:?}",
fatal_err
);
// TODO: we should show a "Reload & Retry" button in the troubleshooter to retry // TODO: we should show a "Reload & Retry" button in the troubleshooter to retry
// loading the configuration and: // loading the configuration and:
@ -244,15 +261,22 @@ fn spawn_worker(paths: &Paths, paths_overrides: &PathsOverrides, exit_notify: Se
unimplemented!(); unimplemented!();
return; return;
}, }
}; };
let mut command = Command::new(&espanso_exe_path.to_string_lossy().to_string()); let mut command = Command::new(&espanso_exe_path.to_string_lossy().to_string());
command.args(&["worker", "--monitor-daemon"]); command.args(&[
"worker",
"--monitor-daemon",
"--run-count",
&format!("{}", worker_run_count),
]);
command.with_paths_overrides(paths_overrides); command.with_paths_overrides(paths_overrides);
let mut child = command.spawn().expect("unable to spawn worker process"); let mut child = command.spawn().expect("unable to spawn worker process");
*worker_run_count += 1;
// Create a monitor thread that will exit with the same non-zero code if // Create a monitor thread that will exit with the same non-zero code if
// the worker thread exits // the worker thread exits
std::thread::Builder::new() std::thread::Builder::new()

View File

@ -72,6 +72,7 @@ pub fn initialize_and_spawn(
ui_event_receiver: Receiver<UIEvent>, ui_event_receiver: Receiver<UIEvent>,
secure_input_receiver: Receiver<SecureInputEvent>, secure_input_receiver: Receiver<SecureInputEvent>,
use_evdev_backend: bool, use_evdev_backend: bool,
run_count: i32,
) -> Result<JoinHandle<ExitMode>> { ) -> Result<JoinHandle<ExitMode>> {
let handle = std::thread::Builder::new() let handle = std::thread::Builder::new()
.name("engine thread".to_string()) .name("engine thread".to_string())
@ -212,7 +213,11 @@ pub fn initialize_and_spawn(
} }
// TODO: check config // TODO: check config
ui_remote.show_notification("Espanso is running!"); match run_count {
0 => ui_remote.show_notification("Espanso is running!"),
1 => ui_remote.show_notification("Configuration reloaded! Espanso automatically loads new changes as soon as you save them."),
_ => {},
}
let mut engine = crate::engine::Engine::new(&funnel, &mut processor, &dispatcher); let mut engine = crate::engine::Engine::new(&funnel, &mut processor, &dispatcher);
let exit_mode = engine.run(); let exit_mode = engine.run();

View File

@ -18,7 +18,7 @@
*/ */
use crossbeam::channel::unbounded; use crossbeam::channel::unbounded;
use log::{error, info}; use log::{debug, error, info};
use crate::{ use crate::{
engine::event::ExitMode, engine::event::ExitMode,
@ -59,6 +59,14 @@ fn worker_main(args: CliModuleArgs) -> i32 {
let paths = args.paths.expect("missing paths in worker main"); let paths = args.paths.expect("missing paths in worker main");
let cli_args = args.cli_args.expect("missing cli_args in worker main"); let cli_args = args.cli_args.expect("missing cli_args in worker main");
// This number is passed by the daemon and incremented at each worker
// restart.
let run_count = cli_args
.value_of("run-count")
.map(|val| val.parse::<i32>().unwrap_or(0))
.unwrap_or(0);
debug!("starting with run-count = {:?}", cli_args);
// Avoid running multiple worker instances // Avoid running multiple worker instances
let lock_file = acquire_worker_lock(&paths.runtime); let lock_file = acquire_worker_lock(&paths.runtime);
if lock_file.is_none() { if lock_file.is_none() {
@ -120,6 +128,7 @@ fn worker_main(args: CliModuleArgs) -> i32 {
engine_ui_event_receiver, engine_ui_event_receiver,
engine_secure_input_receiver, engine_secure_input_receiver,
use_evdev_backend, use_evdev_backend,
run_count,
) )
.expect("unable to initialize engine"); .expect("unable to initialize engine");

View File

@ -331,6 +331,12 @@ fn main() {
.subcommand( .subcommand(
SubCommand::with_name("worker") SubCommand::with_name("worker")
.setting(AppSettings::Hidden) .setting(AppSettings::Hidden)
.arg(
Arg::with_name("run-count")
.long("run-count")
.required(false)
.takes_value(true),
)
.arg( .arg(
Arg::with_name("monitor-daemon") Arg::with_name("monitor-daemon")
.long("monitor-daemon") .long("monitor-daemon")