use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct NodeId(pub u32);
impl std::fmt::Display for NodeId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Node({})", self.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ServiceName(pub String);
impl ServiceName {
pub fn new(s: impl Into<String>) -> Self {
Self(s.into())
}
}
impl std::fmt::Display for ServiceName {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RpcRequest {
pub id: u64,
pub from: NodeId,
pub to: NodeId,
pub service: ServiceName,
pub method: String,
pub args: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RpcResult {
Ok(String),
Err(String),
Timeout,
NodeDown,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RpcResponse {
pub request_id: u64,
pub from: NodeId,
pub to: NodeId,
pub result: RpcResult,
}
#[derive(Debug, Default, Clone)]
pub struct ServiceRegistry {
pub services: HashMap<(NodeId, ServiceName), Vec<String>>,
}
impl ServiceRegistry {
pub fn new() -> Self {
Self::default()
}
pub fn register(&mut self, node: NodeId, service: ServiceName, methods: Vec<String>) {
self.services.insert((node, service), methods);
}
pub fn nodes_for(&self, service: &ServiceName) -> Vec<NodeId> {
self.services
.keys()
.filter_map(|(n, s)| if s == service { Some(*n) } else { None })
.collect()
}
pub fn has_method(&self, node: NodeId, service: &ServiceName, method: &str) -> bool {
self.services
.get(&(node, service.clone()))
.map_or(false, |methods| methods.iter().any(|m| m == method))
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CircuitState {
Closed,
Open,
HalfOpen,
}
#[derive(Debug, Clone)]
pub struct CircuitBreaker {
pub failures: u32,
pub threshold: u32,
pub state: CircuitState,
pub last_attempt: u64,
pub open_duration: u64,
}
impl CircuitBreaker {
pub fn new(threshold: u32, open_duration: u64) -> Self {
Self {
failures: 0,
threshold,
state: CircuitState::Closed,
last_attempt: 0,
open_duration,
}
}
}
#[derive(Debug)]
pub struct RpcNetwork {
pub nodes: Vec<NodeId>,
pub registry: ServiceRegistry,
pub latency_ms: HashMap<(NodeId, NodeId), u64>,
pub message_log: Vec<(RpcRequest, RpcResponse)>,
pub(super) downed_nodes: std::collections::HashSet<NodeId>,
pub(super) next_req_id: u64,
pub(super) clock_ms: u64,
}
impl RpcNetwork {
pub fn new(nodes: Vec<NodeId>) -> Self {
Self {
nodes,
registry: ServiceRegistry::new(),
latency_ms: HashMap::new(),
message_log: Vec::new(),
downed_nodes: std::collections::HashSet::new(),
next_req_id: 0,
clock_ms: 0,
}
}
}