dcs2_raft/
metadata.rs

1use log::{debug, error};
2use rand::{Rng, SeedableRng};
3use rand_chacha::ChaCha20Rng;
4use serde::{Deserialize, Serialize};
5use std::fmt::{Display, Formatter};
6use std::time::SystemTime;
7
8use dcs::config::{get_argument, SystemNodeArgs};
9use dcs::membership::metadata::{BasicMetadata, CoordinationMetadataBuilder, SerializableMetadata};
10use dcs::nodes::NodeRole;
11
12#[derive(Clone, Default, Debug, Serialize, Deserialize)]
13pub struct RaftMetadata {
14    pub timeout: u64,
15}
16
17impl RaftMetadata {
18    pub fn new(timeout: u64) -> Self {
19        Self { timeout }
20    }
21}
22
23impl BasicMetadata for RaftMetadata {}
24
25impl SerializableMetadata for RaftMetadata {}
26
27impl Display for RaftMetadata {
28    fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
29        write!(formatter, "[Timeout: {}]", self.timeout)
30    }
31}
32
33#[derive(Default)]
34pub struct RaftMetadataBuilder;
35
36impl RaftMetadataBuilder {
37    fn randomize_timeout(original_timeout: u64) -> u64 {
38        let seed = SystemTime::now()
39            .duration_since(SystemTime::UNIX_EPOCH)
40            .unwrap()
41            .as_secs();
42        let mut rng = ChaCha20Rng::seed_from_u64(seed);
43        let random_timeout = rng.gen_range(original_timeout..original_timeout * 6);
44        debug!("Random timeout: {}", random_timeout);
45        random_timeout
46    }
47}
48
49impl CoordinationMetadataBuilder<RaftMetadata> for RaftMetadataBuilder {
50    fn build(args: &SystemNodeArgs) -> RaftMetadata {
51        match args.role {
52            NodeRole::SENSOR(_) => {
53                let timeout = get_argument(args.clone().coordination.unwrap(), "timeout")
54                    .and_then(|val| val.parse::<u64>().ok())
55                    .unwrap_or_else(|| {
56                        error!("TIMEOUT argument expected.");
57                        panic!()
58                    });
59
60                let timeout = RaftMetadataBuilder::randomize_timeout(timeout);
61                log::info!("Generated timeout of {} for Raft.", timeout);
62                RaftMetadata::new(timeout)
63            }
64            _ => {
65                error!(
66                    "Shouldn't try to parse Raft metadata for an {:?}.",
67                    args.role
68                );
69                panic!()
70            }
71        }
72    }
73}