mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
util/cli: Add macro for standardized daemonization.
This commit is contained in:
@@ -120,3 +120,97 @@ macro_rules! cli_desc {
|
||||
Box::leak(desc.into_boxed_str()) as &'static str
|
||||
}};
|
||||
}
|
||||
|
||||
/// This macro is used for a standard way of daemonizing darkfi binaries
|
||||
/// with TOML config file configuration, and argument parsing. It also
|
||||
/// spawns a multithreaded async executor and passes it into the given
|
||||
/// function.
|
||||
///
|
||||
/// The Cargo.toml dependencies needed for this are:
|
||||
/// ```text
|
||||
/// async-channel = "1.6.1"
|
||||
/// async-executor = "1.4.1"
|
||||
/// async-std = "1.11.0"
|
||||
/// darkfi = { path = "../../", features = ["util"] }
|
||||
/// easy-parallel = "3.2.0"
|
||||
/// futures-lite = "1.12.0"
|
||||
/// simplelog = "0.12.0-alpha1"
|
||||
///
|
||||
/// # Argument parsing
|
||||
/// serde = "1.0.136"
|
||||
/// serde_derive = "1.0.136"
|
||||
/// structopt = "0.3.26"
|
||||
/// structopt-toml = "0.5.0"
|
||||
/// ```
|
||||
///
|
||||
/// Example usage:
|
||||
/// ```text
|
||||
/// use async_executor::Executor;
|
||||
/// use async_std::sync::Arc;
|
||||
/// use easy_parallel::Parallel;
|
||||
/// use futures_lite::future;
|
||||
/// use simplelog::{ColorChoice, TermLogger, TerminalMode};
|
||||
/// use structopt_toml::{serde::Deserialize, structopt::StructOpt, StructOptToml};
|
||||
///
|
||||
/// use darkfi::{
|
||||
/// async_daemonize, cli_desc,
|
||||
/// util::{
|
||||
/// cli::{log_config, spawn_config},
|
||||
/// path::get_config_path,
|
||||
/// },
|
||||
/// Result,
|
||||
/// };
|
||||
///
|
||||
/// const CONFIG_FILE: &str = "daemond_config.toml";
|
||||
/// const CONFIG_FILE_CONTENTS: &str = include_str!("../daemond_config.toml");
|
||||
///
|
||||
/// #[derive(Clone, Debug, Deserialize, StructOpt, StructOptToml)]
|
||||
/// #[serde(default)]
|
||||
/// #[structopt(name = "daemond", about = cli_desc!())]
|
||||
/// struct Args {
|
||||
/// #[structopt(short, long)]
|
||||
/// /// Configuration file to use
|
||||
/// config: Option<String>,
|
||||
///
|
||||
/// #[structopt(short, parse(from_occurrences))]
|
||||
/// /// Increase verbosity (-vvv supported)
|
||||
/// verbose: u8,
|
||||
/// }
|
||||
///
|
||||
/// async_daemonize!(realmain);
|
||||
/// async fn realmain(args: Args, ex: Arc<Executor<'_>>) -> Result<()> {
|
||||
/// println!("Hello, world!");
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! async_daemonize {
|
||||
($realmain:ident) => {
|
||||
fn main() -> Result<()> {
|
||||
let args = Args::from_args_with_toml("").unwrap();
|
||||
let cfg_path = get_config_path(args.config, CONFIG_FILE)?;
|
||||
spawn_config(&cfg_path, CONFIG_FILE_CONTENTS.as_bytes())?;
|
||||
let args = Args::from_args_with_toml(&std::fs::read_to_string(cfg_path)?).unwrap();
|
||||
|
||||
let (lvl, conf) = log_config(args.verbose.into())?;
|
||||
TermLogger::init(lvl, conf, TerminalMode::Mixed, ColorChoice::Auto)?;
|
||||
|
||||
// https://docs.rs/smol/latest/smol/struct.Executor.html#examples
|
||||
let ex = Arc::new(Executor::new());
|
||||
let (signal, shutdown) = async_channel::unbounded::<()>();
|
||||
let (_, result) = Parallel::new()
|
||||
// Run four executor threads
|
||||
.each(0..4, |_| future::block_on(ex.run(shutdown.recv())))
|
||||
// Run the main future on the current thread.
|
||||
.finish(|| {
|
||||
future::block_on(async {
|
||||
$realmain(args, ex.clone()).await?;
|
||||
drop(signal);
|
||||
Ok::<(), darkfi::Error>(())
|
||||
})
|
||||
});
|
||||
|
||||
result
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user