From 2a7d40dcdcde7c94c421a1fd16d96bcf7cd6d66a Mon Sep 17 00:00:00 2001 From: beeb Date: Thu, 9 Feb 2023 07:47:16 +0100 Subject: [PATCH 1/2] fix: better ctrl-c handling --- src/main.rs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 5992b7d..1b2e272 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,8 @@ use tokio::{task, time}; use backup::backup; use config::parse_config; +use crate::prelude::*; + mod aws; mod backup; mod config; @@ -20,7 +22,8 @@ mod prelude; #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { - dotenv().ok(); + dotenv().ok(); // load .env file if present + // set default logging level. we ignore info logs from aws if env::var("RUST_LOG").is_err() { env::set_var( "RUST_LOG", @@ -29,32 +32,48 @@ async fn main() -> Result<()> { }; env_logger::init(); + // parse config from env and/or cli let params = Arc::new(parse_config().await?); + // check if we run the backup once, or periodically forever match params.interval { Some(interval) => { info!( "Will backup \"{}\" every {interval} seconds", params.folder.to_string_lossy() ); + // spawn a routine that will run the backup periodically let task = task::spawn(async move { let shared_params = Arc::clone(¶ms); let mut interval = time::interval(Duration::from_secs(interval)); loop { - interval.tick().await; + interval.tick().await; // the first tick completes immediately, triggering the backup match backup(&shared_params).await { Ok(_) => { info!("Backup succeeded"); } Err(e) => { + // we handle errors here to keep the loop running error!("Backup error: {e:#}"); } } } }); - task.await?; + let ctrl_c = tokio::spawn(async move { + tokio::signal::ctrl_c().await.or_panic(); + }); + // loop forever, unless ctrl-c is called + tokio::select! { + _ = ctrl_c => { + info!("Ctrl-C received, exiting"); + } + _ = task => { + info!("Backup task exited, exiting"); + } + } } None => { + // run backup only once, immediately info!("Backuping \"{}\" once", params.folder.to_string_lossy()); backup(¶ms) .await From 1fa004722e9af317cea4957e0b25384c2a0550c5 Mon Sep 17 00:00:00 2001 From: beeb Date: Thu, 9 Feb 2023 07:47:16 +0100 Subject: [PATCH 2/2] fix: better ctrl-c handling --- Cargo.lock | 10 ++++++++++ Cargo.toml | 2 +- src/main.rs | 25 ++++++++++++++++++++++--- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f486cbf..c0017e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1446,6 +1446,15 @@ dependencies = [ "digest", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + [[package]] name = "simd-abstraction" version = "0.7.1" @@ -1602,6 +1611,7 @@ dependencies = [ "memchr", "mio", "pin-project-lite", + "signal-hook-registry", "socket2", "tokio-macros", "windows-sys 0.42.0", diff --git a/Cargo.toml b/Cargo.toml index efe1086..53675fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ flate2 = "1" log = "0.4" tar = "0.4" temp-dir = "0.1" -tokio = { version = "1", features = ["rt", "macros"] } +tokio = { version = "1", features = ["rt", "macros", "signal"] } uuid = { version = "1", features = ["v4", "fast-rng"] } [profile.release] diff --git a/src/main.rs b/src/main.rs index 5992b7d..1b2e272 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,8 @@ use tokio::{task, time}; use backup::backup; use config::parse_config; +use crate::prelude::*; + mod aws; mod backup; mod config; @@ -20,7 +22,8 @@ mod prelude; #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { - dotenv().ok(); + dotenv().ok(); // load .env file if present + // set default logging level. we ignore info logs from aws if env::var("RUST_LOG").is_err() { env::set_var( "RUST_LOG", @@ -29,32 +32,48 @@ async fn main() -> Result<()> { }; env_logger::init(); + // parse config from env and/or cli let params = Arc::new(parse_config().await?); + // check if we run the backup once, or periodically forever match params.interval { Some(interval) => { info!( "Will backup \"{}\" every {interval} seconds", params.folder.to_string_lossy() ); + // spawn a routine that will run the backup periodically let task = task::spawn(async move { let shared_params = Arc::clone(¶ms); let mut interval = time::interval(Duration::from_secs(interval)); loop { - interval.tick().await; + interval.tick().await; // the first tick completes immediately, triggering the backup match backup(&shared_params).await { Ok(_) => { info!("Backup succeeded"); } Err(e) => { + // we handle errors here to keep the loop running error!("Backup error: {e:#}"); } } } }); - task.await?; + let ctrl_c = tokio::spawn(async move { + tokio::signal::ctrl_c().await.or_panic(); + }); + // loop forever, unless ctrl-c is called + tokio::select! { + _ = ctrl_c => { + info!("Ctrl-C received, exiting"); + } + _ = task => { + info!("Backup task exited, exiting"); + } + } } None => { + // run backup only once, immediately info!("Backuping \"{}\" once", params.folder.to_string_lossy()); backup(¶ms) .await