feat: add option to activate continuous monitoring on config file
This commit is contained in:
parent
86daa0a61b
commit
411fbaf296
8 changed files with 216 additions and 30 deletions
|
|
@ -3,25 +3,44 @@ use crate::{
|
|||
cert_file_reader::CryptoFileSource,
|
||||
error::{anyhow, ensure},
|
||||
};
|
||||
use clap::Arg;
|
||||
use clap::{Arg, ArgAction};
|
||||
use rpxy_lib::{AppConfig, AppConfigList, ProxyConfig};
|
||||
|
||||
pub fn parse_opts() -> Result<String, anyhow::Error> {
|
||||
/// Parsed options
|
||||
pub struct Opts {
|
||||
pub config_file_path: String,
|
||||
pub watch: bool,
|
||||
}
|
||||
|
||||
/// Parse arg values passed from cli
|
||||
pub fn parse_opts() -> Result<Opts, anyhow::Error> {
|
||||
let _ = include_str!("../../Cargo.toml");
|
||||
let options = clap::command!().arg(
|
||||
Arg::new("config_file")
|
||||
.long("config")
|
||||
.short('c')
|
||||
.value_name("FILE")
|
||||
.required(true)
|
||||
.help("Configuration file path like ./config.toml"),
|
||||
);
|
||||
let options = clap::command!()
|
||||
.arg(
|
||||
Arg::new("config_file")
|
||||
.long("config")
|
||||
.short('c')
|
||||
.value_name("FILE")
|
||||
.required(true)
|
||||
.help("Configuration file path like ./config.toml"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("watch")
|
||||
.long("watch")
|
||||
.short('w')
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("Activate dynamic reloading of the config file via continuous monitoring"),
|
||||
);
|
||||
let matches = options.get_matches();
|
||||
|
||||
///////////////////////////////////
|
||||
let config_file_path = matches.get_one::<String>("config_file").unwrap();
|
||||
let config_file_path = matches.get_one::<String>("config_file").unwrap().to_owned();
|
||||
let watch = matches.get_one::<bool>("watch").unwrap().to_owned();
|
||||
|
||||
Ok(config_file_path.to_string())
|
||||
Ok(Opts {
|
||||
config_file_path,
|
||||
watch,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn build_settings(
|
||||
|
|
|
|||
|
|
@ -28,32 +28,69 @@ fn main() {
|
|||
let runtime = runtime_builder.build().unwrap();
|
||||
|
||||
runtime.block_on(async {
|
||||
// Initially load config
|
||||
let Ok(config_path) = parse_opts() else {
|
||||
// Initially load options
|
||||
let Ok(parsed_opts) = parse_opts() else {
|
||||
error!("Invalid toml file");
|
||||
std::process::exit(1);
|
||||
};
|
||||
let (config_service, config_rx) =
|
||||
ReloaderService::<ConfigTomlReloader, ConfigToml>::new(&config_path, CONFIG_WATCH_DELAY_SECS, false)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
tokio::select! {
|
||||
_ = config_service.start() => {
|
||||
error!("config reloader service exited");
|
||||
if !parsed_opts.watch {
|
||||
if let Err(e) = rpxy_service_without_watcher(&parsed_opts.config_file_path, runtime.handle().clone()).await {
|
||||
error!("rpxy service existed: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
_ = rpxy_service(config_rx, runtime.handle().clone()) => {
|
||||
error!("rpxy service existed");
|
||||
} else {
|
||||
let (config_service, config_rx) = ReloaderService::<ConfigTomlReloader, ConfigToml>::new(
|
||||
&parsed_opts.config_file_path,
|
||||
CONFIG_WATCH_DELAY_SECS,
|
||||
false,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
tokio::select! {
|
||||
Err(e) = config_service.start() => {
|
||||
error!("config reloader service exited: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
Err(e) = rpxy_service_with_watcher(config_rx, runtime.handle().clone()) => {
|
||||
error!("rpxy service existed: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async fn rpxy_service(
|
||||
mut config_rx: ReloaderReceiver<ConfigToml>,
|
||||
async fn rpxy_service_without_watcher(
|
||||
config_file_path: &str,
|
||||
runtime_handle: tokio::runtime::Handle,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
info!("Start rpxy service");
|
||||
let config_toml = match ConfigToml::new(config_file_path) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
error!("Invalid toml file: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
let (proxy_conf, app_conf) = match build_settings(&config_toml) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
error!("Invalid configuration: {e}");
|
||||
return Err(anyhow::anyhow!(e));
|
||||
}
|
||||
};
|
||||
entrypoint(&proxy_conf, &app_conf, &runtime_handle)
|
||||
.await
|
||||
.map_err(|e| anyhow::anyhow!(e))
|
||||
}
|
||||
|
||||
async fn rpxy_service_with_watcher(
|
||||
mut config_rx: ReloaderReceiver<ConfigToml>,
|
||||
runtime_handle: tokio::runtime::Handle,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
info!("Start rpxy service with dynamic config reloader");
|
||||
// Initial loading
|
||||
config_rx.changed().await?;
|
||||
let config_toml = config_rx.borrow().clone().unwrap();
|
||||
|
|
@ -92,5 +129,6 @@ async fn rpxy_service(
|
|||
else => break
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
Err(anyhow::anyhow!("rpxy or continuous monitoring service exited"))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue