use std::collections::HashMap;
pub type FederatedResult<T> = Result<T, FederatedError>;
#[derive(Debug, Clone, PartialEq)]
pub enum FederatedError {
HostNotFound { host_id: String },
PartitionDetected { affected_hosts: Vec<String> },
MergeConflict { reason: String },
ClockDriftExceeded { drift_ms: i64, max_ms: i64 },
MemoryLimitExceeded {
used_bytes: usize,
limit_bytes: usize,
},
InvalidConfig { reason: String },
}
impl std::fmt::Display for FederatedError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::HostNotFound { host_id } => write!(f, "Host not found: {}", host_id),
Self::PartitionDetected { affected_hosts } => {
write!(f, "Partition detected affecting: {:?}", affected_hosts)
}
Self::MergeConflict { reason } => write!(f, "Merge conflict: {}", reason),
Self::ClockDriftExceeded { drift_ms, max_ms } => {
write!(f, "Clock drift {}ms exceeds max {}ms", drift_ms, max_ms)
}
Self::MemoryLimitExceeded {
used_bytes,
limit_bytes,
} => {
write!(f, "Memory {} exceeds limit {}", used_bytes, limit_bytes)
}
Self::InvalidConfig { reason } => write!(f, "Invalid config: {}", reason),
}
}
}
impl std::error::Error for FederatedError {}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SampleId {
pub host_id: String,
pub logical_time: u64,
pub sequence: u64,
}
impl SampleId {
pub fn new(host_id: impl Into<String>, logical_time: u64, sequence: u64) -> Self {
Self {
host_id: host_id.into(),
logical_time,
sequence,
}
}
}
#[derive(Debug, Clone)]
pub struct MetricSample {
pub id: SampleId,
pub metric_name: String,
pub value: f64,
pub timestamp_ns: u64,
pub vector_clock: HashMap<String, u64>,
}
impl MetricSample {
pub fn new(
host_id: impl Into<String>,
logical_time: u64,
sequence: u64,
metric_name: impl Into<String>,
value: f64,
) -> Self {
let host = host_id.into();
let mut vector_clock = HashMap::new();
vector_clock.insert(host.clone(), logical_time);
Self {
id: SampleId::new(host, logical_time, sequence),
metric_name: metric_name.into(),
value,
timestamp_ns: std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_nanos() as u64)
.unwrap_or(0),
vector_clock,
}
}
}