cat_gateway/settings/
chain_follower.rs

1//! Command line and environment variable settings for the service
2
3use std::{cmp::min, time::Duration};
4
5use cardano_blockchain_types::Network;
6use cardano_chain_follower::{turbo_downloader::DlConfig, ChainSyncConfig};
7use tracing::info;
8
9use super::str_env_var::StringEnvVar;
10
11/// Default chain to follow.
12const DEFAULT_NETWORK: Network = Network::Mainnet;
13
14/// Default number of sync tasks (must be in the range 1 to 256 inclusive.)
15const DEFAULT_SYNC_TASKS: u16 = 16;
16
17/// Maximum number of sync tasks (must be in the range 1 to 256 inclusive.)
18const MAX_SYNC_TASKS: u16 = 256;
19
20/// Default number of slots each sync task will process at one time.
21/// This default is just over one week worth of data where 1 slot == 1 second.
22const DEFAULT_SYNC_MAX_SLOTS: u64 = 700_000;
23/// Minimum the number of slots each sync task will process at one time can be set to.
24/// Note: This is just the setting minimum, a sync task may sync as few as a 1 slot.
25const MIN_SYNC_MAX_SLOTS: u64 = 10_000;
26/// Maximum the number of slots each sync task will process at one time can be set to.
27const MAX_SYNC_MAX_SLOTS: u64 = 100_000_000;
28
29/// Maximum number of DL Connections (must be in the range 1 to 256 inclusive.)
30const MAX_DL_CONNECTIONS: usize = 256;
31
32/// Maximum DL Chunk Size in MB (must be in the range 1 to 256 inclusive.)
33const MAX_DL_CHUNK_SIZE: usize = 256;
34
35/// Maximum DL Chunk Queue Ahead (must be in the range 1 to 256 inclusive.)
36const MAX_DL_CHUNK_QUEUE_AHEAD: usize = 256;
37
38/// Maximum DL Chunk Connect/Data Timeout in seconds (0 = Disabled).
39const MAX_DL_TIMEOUT: u64 = 300;
40
41/// Number of bytes in a Megabyte
42const ONE_MEGABYTE: usize = 1_048_576;
43
44/// Configuration for the chain follower.
45#[derive(Clone)]
46pub(crate) struct EnvVars {
47    /// The Blockchain we sync from.
48    pub(crate) chain: Network,
49
50    /// The maximum number of sync tasks.
51    pub(crate) sync_tasks: u16,
52
53    /// The maximum number of slots a sync task will process at once.
54    pub(crate) sync_chunk_max_slots: u64,
55
56    /// The Mithril Downloader Configuration.
57    pub(crate) dl_config: DlConfig,
58}
59
60impl EnvVars {
61    /// Create a config for a cassandra cluster, identified by a default namespace.
62    pub(super) fn new() -> Self {
63        let chain = StringEnvVar::new_as_enum("CHAIN_NETWORK", DEFAULT_NETWORK, false);
64        let sync_tasks: u16 = StringEnvVar::new_as_int(
65            "CHAIN_FOLLOWER_SYNC_TASKS",
66            DEFAULT_SYNC_TASKS,
67            1,
68            MAX_SYNC_TASKS,
69        );
70
71        let sync_slots: u64 = StringEnvVar::new_as_int(
72            "CHAIN_FOLLOWER_SYNC_MAX_SLOTS",
73            DEFAULT_SYNC_MAX_SLOTS,
74            MIN_SYNC_MAX_SLOTS,
75            MAX_SYNC_MAX_SLOTS,
76        );
77
78        let cfg = ChainSyncConfig::default_for(chain);
79        let mut dl_config = cfg.mithril_cfg.dl_config.clone().unwrap_or_default();
80
81        let workers = StringEnvVar::new_as_int(
82            "CHAIN_FOLLOWER_DL_CONNECTIONS",
83            dl_config.workers,
84            1,
85            MAX_DL_CONNECTIONS,
86        );
87        dl_config = dl_config.with_workers(workers);
88
89        let default_dl_chunk_size = min(1, dl_config.chunk_size / ONE_MEGABYTE);
90
91        let chunk_size = StringEnvVar::new_as_int(
92            "CHAIN_FOLLOWER_DL_CHUNK_SIZE",
93            default_dl_chunk_size,
94            1,
95            MAX_DL_CHUNK_SIZE,
96        )
97        .checked_mul(ONE_MEGABYTE)
98        .unwrap_or_else(|| {
99            info!("Too big 'CHAIN_FOLLOWER_DL_CHUNK_SIZE' value, default value {default_dl_chunk_size} is used");
100            default_dl_chunk_size
101        });
102        dl_config = dl_config.with_chunk_size(chunk_size);
103
104        let queue_ahead = StringEnvVar::new_as_int(
105            "CHAIN_FOLLOWER_DL_QUEUE_AHEAD",
106            dl_config.queue_ahead,
107            1,
108            MAX_DL_CHUNK_QUEUE_AHEAD,
109        );
110        dl_config = dl_config.with_queue_ahead(queue_ahead);
111
112        let default_dl_connect_timeout = match dl_config.connection_timeout {
113            Some(timeout) => timeout.as_secs(),
114            None => 0,
115        };
116        let dl_connect_timeout = StringEnvVar::new_as_int(
117            "CHAIN_FOLLOWER_DL_CONNECT_TIMEOUT",
118            default_dl_connect_timeout,
119            0,
120            MAX_DL_TIMEOUT,
121        );
122        if dl_connect_timeout == 0 {
123            dl_config.connection_timeout = None;
124        } else {
125            dl_config = dl_config.with_connection_timeout(Duration::from_secs(dl_connect_timeout));
126        }
127
128        let default_dl_data_timeout = match dl_config.data_read_timeout {
129            Some(timeout) => timeout.as_secs(),
130            None => 0,
131        };
132        let dl_data_timeout = StringEnvVar::new_as_int(
133            "CHAIN_FOLLOWER_DL_DATA_TIMEOUT",
134            default_dl_data_timeout,
135            0,
136            MAX_DL_TIMEOUT,
137        );
138        if dl_connect_timeout == 0 {
139            dl_config.data_read_timeout = None;
140        } else {
141            dl_config = dl_config.with_data_read_timeout(Duration::from_secs(dl_data_timeout));
142        }
143
144        Self {
145            chain,
146            sync_tasks,
147            sync_chunk_max_slots: sync_slots,
148            dl_config,
149        }
150    }
151
152    /// Log the configuration of this Chain Follower
153    pub(crate) fn log(&self) {
154        info!(
155            chain = self.chain.to_string(),
156            sync_tasks = self.sync_tasks,
157            dl_config = ?self.dl_config,
158            "Chain Follower Configuration"
159        );
160    }
161}