Skip to main content

near_dyn_configs/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use near_chain_configs::UpdatableClientConfig;
4use near_o11y::log_config::LogConfig;
5use near_primitives::validator_signer::ValidatorSigner;
6use near_time::Clock;
7use std::path::PathBuf;
8use std::sync::Arc;
9use tokio::sync::broadcast::Sender;
10
11mod metrics;
12
13#[derive(Clone, Default)]
14pub enum UpdatableValidatorSigner {
15    /// Validator key existence could not be determined.
16    #[default]
17    KeyExistenceNotDetermined,
18    /// The new state of the validator key.
19    MaybeKey(Option<Arc<ValidatorSigner>>),
20}
21
22#[derive(Clone, Default)]
23/// Contains the latest state of configs which can be updated at runtime.
24pub struct UpdatableConfigs {
25    /// Contents of the file LOG_CONFIG_FILENAME.
26    pub log_config: Option<LogConfig>,
27    /// Contents of the `config.json` corresponding to the mutable fields of `ClientConfig`.
28    pub client_config: Option<UpdatableClientConfig>,
29    /// Validator key hot loaded from file.
30    pub validator_signer: UpdatableValidatorSigner,
31}
32
33/// Pushes the updates to listeners.
34#[derive(Default)]
35pub struct UpdatableConfigLoader {
36    /// Notifies receivers about the new config values available.
37    tx: Option<Sender<Result<UpdatableConfigs, Arc<UpdatableConfigLoaderError>>>>,
38}
39
40#[derive(thiserror::Error, Debug)]
41#[non_exhaustive]
42pub enum UpdatableConfigLoaderError {
43    #[error("Failed to parse a dynamic config file {file:?}: {err:?}")]
44    Parse { file: PathBuf, err: serde_json::Error },
45    #[error("Can't open or read a dynamic config file {file:?}: {err:?}")]
46    OpenAndRead { file: PathBuf, err: std::io::Error },
47    #[error("Can't open or read the config file {file:?}: {err:?}")]
48    ConfigFileError { file: PathBuf, err: anyhow::Error },
49    #[error("Can't open or read the validator key file {file:?}: {err:?}")]
50    ValidatorKeyFileError { file: PathBuf, err: anyhow::Error },
51    #[error("One or multiple dynamic config files reload errors {0:?}")]
52    Errors(Vec<UpdatableConfigLoaderError>),
53    #[error("No home dir set")]
54    NoHomeDir(),
55}
56
57impl UpdatableConfigLoader {
58    pub fn new(
59        updatable_configs: UpdatableConfigs,
60        tx: Sender<Result<UpdatableConfigs, Arc<UpdatableConfigLoaderError>>>,
61    ) -> Self {
62        let mut result = Self { tx: Some(tx) };
63        result.reload(Ok(updatable_configs));
64        result
65    }
66
67    pub fn reload(
68        &mut self,
69        updatable_configs: Result<UpdatableConfigs, UpdatableConfigLoaderError>,
70    ) {
71        match updatable_configs {
72            Ok(updatable_configs) => {
73                near_o11y::reload_log_config(updatable_configs.log_config.as_ref());
74                self.tx.as_ref().map(|tx| tx.send(Ok(updatable_configs.clone())));
75                Self::update_metrics();
76            }
77            Err(err) => {
78                self.tx.as_ref().map(|tx| tx.send(Err(Arc::new(err))));
79            }
80        }
81    }
82
83    fn update_metrics() {
84        metrics::CONFIG_RELOAD_TIMESTAMP.set(Clock::real().now_utc().unix_timestamp());
85        metrics::CONFIG_RELOADS.inc();
86    }
87}