#[cfg(all(feature = "reload", feature = "yaml"))]
use hexcfg::prelude::*;
#[cfg(all(feature = "reload", feature = "yaml"))]
use std::sync::{Arc, Mutex};
#[cfg(all(feature = "reload", feature = "yaml"))]
use std::thread;
#[cfg(all(feature = "reload", feature = "yaml"))]
use std::time::Duration;
#[cfg(all(feature = "reload", feature = "yaml"))]
fn main() -> Result<()> {
tracing_subscriber::fmt::init();
println!("=== Configuration Crate: Dynamic Reload Example ===\n");
let yaml_content = r#"
app:
name: "InitialApp"
port: 8080
environment: "development"
database:
host: "localhost"
port: 5432
max_connections: 10
features:
logging: true
metrics: false
"#;
let temp_file = tempfile::NamedTempFile::new()?;
std::fs::write(temp_file.path(), yaml_content)?;
println!("Created config file at: {:?}", temp_file.path());
println!("Initial configuration:\n{}\n", yaml_content);
let service = Arc::new(Mutex::new(
ConfigurationServiceBuilder::new()
.with_yaml_file(temp_file.path())?
.build()?,
));
println!("=== Initial Configuration Values ===");
print_config_values(&service.lock().unwrap());
let mut watcher = FileWatcher::new(temp_file.path(), Some(Duration::from_secs(1)))?;
let service_clone = Arc::clone(&service);
let callback = Arc::new(move |key: ConfigKey| {
println!("\n🔄 Configuration change detected: {}", key);
println!("Reloading configuration...");
if let Ok(mut svc) = service_clone.lock() {
if let Err(e) = svc.reload() {
eprintln!("Error reloading configuration: {}", e);
return;
}
println!("\n=== Updated Configuration Values ===");
print_config_values(&svc);
}
});
println!("\n=== Starting Configuration Watcher ===");
println!("Watching for changes to: {:?}", temp_file.path());
println!("Debounce delay: 1 second");
println!("\nTry modifying the configuration file in another terminal:");
println!(" echo 'app:");
println!(" name: UpdatedApp");
println!(" port: 9000' > {:?}", temp_file.path());
watcher.watch(callback)?;
println!("\nApplication is running. Press Ctrl+C to exit.");
println!("The application will automatically reload configuration when the file changes.\n");
for i in 1..=30 {
thread::sleep(Duration::from_secs(2));
print!(".");
std::io::Write::flush(&mut std::io::stdout()).unwrap();
if i % 10 == 0 {
println!();
}
}
println!("\n\n=== Stopping Watcher ===");
watcher.stop()?;
println!("Example complete. Configuration watcher stopped.");
Ok(())
}
#[cfg(all(feature = "reload", feature = "yaml"))]
fn print_config_values(service: &DefaultConfigService) {
let keys = vec![
("app.name", "string"),
("app.port", "integer"),
("app.environment", "string"),
("database.host", "string"),
("database.port", "integer"),
("database.max_connections", "integer"),
("features.logging", "boolean"),
("features.metrics", "boolean"),
];
for (key, value_type) in keys {
let config_key = ConfigKey::from(key);
match service.get(&config_key) {
Ok(value) => {
let formatted_value = match value_type {
"integer" => value
.as_i32(key)
.map(|v| v.to_string())
.unwrap_or_else(|_| value.as_str().to_string()),
"boolean" => value
.as_bool(key)
.map(|v| v.to_string())
.unwrap_or_else(|_| value.as_str().to_string()),
_ => value.as_str().to_string(),
};
println!(" {:<30} = {}", key, formatted_value);
}
Err(_) => {
println!(" {:<30} = <not set>", key);
}
}
}
}
#[cfg(not(all(feature = "reload", feature = "yaml")))]
fn main() {
eprintln!("Error: This example requires the 'reload' and 'yaml' features.");
eprintln!("Run with: cargo run --example dynamic_reload --features yaml,reload");
std::process::exit(1);
}