forge_core/cluster/
traits.rs1use super::node::NodeId;
2use super::roles::LeaderRole;
3
4#[derive(Debug, Clone)]
6pub struct ClusterInfo {
7 pub name: String,
9 pub total_nodes: usize,
11 pub active_nodes: usize,
13 pub draining_nodes: usize,
15 pub dead_nodes: usize,
17 pub scheduler_leader: Option<NodeId>,
19}
20
21impl ClusterInfo {
22 pub fn empty(name: impl Into<String>) -> Self {
23 Self {
24 name: name.into(),
25 total_nodes: 0,
26 active_nodes: 0,
27 draining_nodes: 0,
28 dead_nodes: 0,
29 scheduler_leader: None,
30 }
31 }
32}
33
34#[derive(Debug, Clone)]
36pub struct LeaderInfo {
37 pub role: LeaderRole,
38 pub node_id: NodeId,
39 pub acquired_at: chrono::DateTime<chrono::Utc>,
40 pub lease_until: chrono::DateTime<chrono::Utc>,
41}
42
43impl LeaderInfo {
44 pub fn is_valid(&self) -> bool {
45 self.lease_until > chrono::Utc::now()
46 }
47}
48
49#[cfg(test)]
50#[allow(clippy::unwrap_used, clippy::indexing_slicing)]
51mod tests {
52 use super::*;
53
54 #[test]
55 fn test_cluster_info_empty() {
56 let info = ClusterInfo::empty("test-cluster");
57 assert_eq!(info.name, "test-cluster");
58 assert_eq!(info.total_nodes, 0);
59 assert_eq!(info.active_nodes, 0);
60 assert!(info.scheduler_leader.is_none());
61 }
62
63 #[test]
64 fn test_leader_info_validity() {
65 let node_id = NodeId::new();
66 let info = LeaderInfo {
67 role: LeaderRole::Scheduler,
68 node_id,
69 acquired_at: chrono::Utc::now(),
70 lease_until: chrono::Utc::now() + chrono::Duration::minutes(1),
71 };
72 assert!(info.is_valid());
73
74 let expired_info = LeaderInfo {
75 role: LeaderRole::Scheduler,
76 node_id,
77 acquired_at: chrono::Utc::now() - chrono::Duration::minutes(5),
78 lease_until: chrono::Utc::now() - chrono::Duration::minutes(1),
79 };
80 assert!(!expired_info.is_valid());
81 }
82}