dcs2-raft 0.1.0

An extensible distributed control system framework made in rust with no-std support.
Documentation
use log::{debug, error};
use rand::{Rng, SeedableRng};
use rand_chacha::ChaCha20Rng;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
use std::time::SystemTime;

use dcs::config::{get_argument, SystemNodeArgs};
use dcs::membership::metadata::{BasicMetadata, CoordinationMetadataBuilder, SerializableMetadata};
use dcs::nodes::NodeRole;

#[derive(Clone, Default, Debug, Serialize, Deserialize)]
pub struct RaftMetadata {
    pub timeout: u64,
}

impl RaftMetadata {
    pub fn new(timeout: u64) -> Self {
        Self { timeout }
    }
}

impl BasicMetadata for RaftMetadata {}

impl SerializableMetadata for RaftMetadata {}

impl Display for RaftMetadata {
    fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
        write!(formatter, "[Timeout: {}]", self.timeout)
    }
}

#[derive(Default)]
pub struct RaftMetadataBuilder;

impl RaftMetadataBuilder {
    fn randomize_timeout(original_timeout: u64) -> u64 {
        let seed = SystemTime::now()
            .duration_since(SystemTime::UNIX_EPOCH)
            .unwrap()
            .as_secs();
        let mut rng = ChaCha20Rng::seed_from_u64(seed);
        let random_timeout = rng.gen_range(original_timeout..original_timeout * 6);
        debug!("Random timeout: {}", random_timeout);
        random_timeout
    }
}

impl CoordinationMetadataBuilder<RaftMetadata> for RaftMetadataBuilder {
    fn build(args: &SystemNodeArgs) -> RaftMetadata {
        match args.role {
            NodeRole::SENSOR(_) => {
                let timeout = get_argument(args.clone().coordination.unwrap(), "timeout")
                    .and_then(|val| val.parse::<u64>().ok())
                    .unwrap_or_else(|| {
                        error!("TIMEOUT argument expected.");
                        panic!()
                    });

                let timeout = RaftMetadataBuilder::randomize_timeout(timeout);
                log::info!("Generated timeout of {} for Raft.", timeout);
                RaftMetadata::new(timeout)
            }
            _ => {
                error!(
                    "Shouldn't try to parse Raft metadata for an {:?}.",
                    args.role
                );
                panic!()
            }
        }
    }
}