gossip_server/config/
mod.rs1use std::path::PathBuf;
2
3use config::{Config, ConfigError, File};
4use dfir_rs::futures::future::ready;
5use dfir_rs::futures::{Stream, StreamExt};
6use notify::{Event, EventHandler, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
7use serde::{Deserialize, Serialize};
8use tokio::sync::mpsc::UnboundedSender;
9use tracing::trace;
10
11#[derive(Debug, Deserialize, Serialize)]
13pub struct ServerSettings {
14 pub seed_nodes: Vec<SeedNodeSettings>,
17}
18
19const CONFIG_ROOT: &str = "config";
20const STATIC_CONFIG_PATH: &str = "static";
21const DYNAMIC_CONFIG_PATH: &str = "dynamic";
22
23fn static_config_path(subpath: &str) -> PathBuf {
24 PathBuf::from(CONFIG_ROOT)
25 .join(STATIC_CONFIG_PATH)
26 .join(subpath)
27}
28
29fn dynamic_config_path(subpath: &str) -> PathBuf {
30 PathBuf::from(CONFIG_ROOT)
31 .join(DYNAMIC_CONFIG_PATH)
32 .join(subpath)
33}
34
35impl ServerSettings {
36 pub fn new() -> Result<Self, ConfigError> {
38 let run_mode = std::env::var("RUN_MODE").unwrap_or_else(|_| "development".into());
39
40 let settings = Config::builder()
41 .add_source(File::from(static_config_path("default.toml")).required(false))
43
44 .add_source(File::from(static_config_path(&run_mode)).required(false))
46
47 .add_source(File::from(static_config_path("local")).required(false))
50
51 .add_source(File::from(dynamic_config_path("dynamic.toml")).required(false))
53 .build()?;
54
55 settings.try_deserialize()
56 }
57}
58
59#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Hash)]
61pub struct SeedNodeSettings {
62 pub id: String,
64
65 pub address: String,
67}
68
69pub fn setup_settings_watch() -> (
75 RecommendedWatcher,
76 ServerSettings,
77 impl Stream<Item = ServerSettings>,
78) {
79 let (tx, rx) = dfir_rs::util::unbounded_channel();
80
81 let mut watcher = RecommendedWatcher::new(
83 UnboundedSenderEventHandler::new(tx),
84 notify::Config::default(),
85 )
86 .unwrap();
87 watcher
88 .watch(&PathBuf::from(CONFIG_ROOT), RecursiveMode::Recursive)
89 .unwrap();
90
91 let initial_settings = ServerSettings::new().unwrap();
93
94 let change_stream = rx
95 .map(Result::unwrap)
96 .map(|event| {
97 trace!("Event: {:?}", event);
98 match event.kind {
99 EventKind::Create(_) | EventKind::Modify(_) | EventKind::Remove(_) => {
100 Some(ServerSettings::new().unwrap())
101 }
102 _ => {
103 trace!("Unhandled event: {:?}", event);
104 None
105 }
106 }
107 })
108 .filter_map(ready);
109
110 (watcher, initial_settings, change_stream)
112}
113
114struct UnboundedSenderEventHandler {
117 tx: UnboundedSender<notify::Result<Event>>,
118}
119
120impl UnboundedSenderEventHandler {
121 fn new(tx: UnboundedSender<notify::Result<Event>>) -> Self {
122 Self { tx }
123 }
124}
125
126impl EventHandler for UnboundedSenderEventHandler {
127 fn handle_event(&mut self, event: notify::Result<Event>) {
128 self.tx.send(event).unwrap();
129 }
130}