1#![doc = include_str!("../README.md")]
2
3use serde::{Deserialize, Serialize};
4use std::path::PathBuf;
5use std::sync::Arc;
6use tokio::sync::broadcast::Sender;
7use unc_chain_configs::UpdateableClientConfig;
8use unc_o11y::log_config::LogConfig;
9use unc_primitives::static_clock::StaticClock;
10
11mod metrics;
12
13#[derive(Serialize, Deserialize, Clone, Default)]
14pub struct UpdateableConfigs {
16 pub log_config: Option<LogConfig>,
18 pub client_config: Option<UpdateableClientConfig>,
20}
21
22#[derive(Default)]
24pub struct UpdateableConfigLoader {
25 tx: Option<Sender<Result<UpdateableConfigs, Arc<UpdateableConfigLoaderError>>>>,
27}
28
29#[derive(thiserror::Error, Debug)]
30#[non_exhaustive]
31pub enum UpdateableConfigLoaderError {
32 #[error("Failed to parse a dynamic config file {file:?}: {err:?}")]
33 Parse { file: PathBuf, err: serde_json::Error },
34 #[error("Can't open or read a dynamic config file {file:?}: {err:?}")]
35 OpenAndRead { file: PathBuf, err: std::io::Error },
36 #[error("Can't open or read the config file {file:?}: {err:?}")]
37 ConfigFileError { file: PathBuf, err: anyhow::Error },
38 #[error("One or multiple dynamic config files reload errors {0:?}")]
39 Errors(Vec<UpdateableConfigLoaderError>),
40 #[error("No home dir set")]
41 NoHomeDir(),
42}
43
44impl UpdateableConfigLoader {
45 pub fn new(
46 updateable_configs: UpdateableConfigs,
47 tx: Sender<Result<UpdateableConfigs, Arc<UpdateableConfigLoaderError>>>,
48 ) -> Self {
49 let mut result = Self { tx: Some(tx) };
50 result.reload(Ok(updateable_configs));
51 result
52 }
53
54 pub fn reload(
55 &mut self,
56 updateable_configs: Result<UpdateableConfigs, UpdateableConfigLoaderError>,
57 ) {
58 match updateable_configs {
59 Ok(updateable_configs) => {
60 unc_o11y::reload_log_config(updateable_configs.log_config.as_ref());
61 self.tx.as_ref().map(|tx| tx.send(Ok(updateable_configs.clone())));
62 Self::update_metrics();
63 }
64 Err(err) => {
65 self.tx.as_ref().map(|tx| tx.send(Err(Arc::new(err))));
66 }
67 }
68 }
69
70 fn update_metrics() {
71 metrics::CONFIG_RELOAD_TIMESTAMP.set(StaticClock::utc().timestamp());
72 metrics::CONFIG_RELOADS.inc();
73 }
74}