1use crate::NodeId;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6use std::net::SocketAddr;
7
8#[derive(Clone, Debug, Serialize, Deserialize)]
10pub struct Member {
11 pub id: NodeId,
13 pub addr: SocketAddr,
15 pub state: MemberState,
17 pub metadata: HashMap<String, String>,
19 pub last_seen: chrono::DateTime<chrono::Utc>,
21}
22
23impl Member {
24 pub fn new(id: NodeId, addr: SocketAddr) -> Self {
26 Self {
27 id,
28 addr,
29 state: MemberState::Alive,
30 metadata: HashMap::new(),
31 last_seen: chrono::Utc::now(),
32 }
33 }
34
35 pub fn is_alive(&self) -> bool {
37 self.state == MemberState::Alive
38 }
39}
40
41#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
43pub enum MemberState {
44 Alive,
46 Suspect,
48 Dead,
50 Left,
52}
53
54impl MemberState {
55 pub fn as_str(&self) -> &'static str {
57 match self {
58 MemberState::Alive => "alive",
59 MemberState::Suspect => "suspect",
60 MemberState::Dead => "dead",
61 MemberState::Left => "left",
62 }
63 }
64}
65
66#[derive(Clone, Debug)]
68pub enum MembershipEvent {
69 Joined(Member),
71 Left(NodeId),
73 StateChanged {
75 id: NodeId,
76 old: MemberState,
77 new: MemberState,
78 },
79 MetadataChanged {
81 id: NodeId,
82 key: String,
83 value: Option<String>,
84 },
85}
86
87#[derive(Clone, Debug)]
89pub struct ClusterState {
90 pub local: Member,
92 pub members: Vec<Member>,
94 pub alive_count: usize,
96}
97
98impl ClusterState {
99 pub fn get_member(&self, id: &NodeId) -> Option<&Member> {
101 self.members.iter().find(|m| &m.id == id)
102 }
103
104 pub fn alive_members(&self) -> impl Iterator<Item = &Member> {
106 self.members.iter().filter(|m| m.is_alive())
107 }
108}
109
110#[derive(Clone, Debug)]
112pub struct ClusterConfig {
113 pub bind_addr: SocketAddr,
115 pub seeds: Vec<SocketAddr>,
117 pub cluster_name: String,
119 pub gossip_interval: std::time::Duration,
121 pub failure_timeout: std::time::Duration,
123 pub metadata: std::collections::HashMap<String, String>,
125}
126
127impl Default for ClusterConfig {
128 fn default() -> Self {
129 Self {
130 bind_addr: "0.0.0.0:7000".parse().unwrap(),
131 seeds: Vec::new(),
132 cluster_name: "pollen".to_string(),
133 gossip_interval: std::time::Duration::from_millis(200),
134 failure_timeout: std::time::Duration::from_secs(5),
135 metadata: std::collections::HashMap::new(),
136 }
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143
144 #[test]
145 fn test_member_is_alive() {
146 let mut member = Member::new(NodeId::new(), "127.0.0.1:7000".parse().unwrap());
147 assert!(member.is_alive());
148
149 member.state = MemberState::Dead;
150 assert!(!member.is_alive());
151 }
152
153 #[test]
154 fn test_cluster_config_default() {
155 let config = ClusterConfig::default();
156 assert_eq!(config.cluster_name, "pollen");
157 assert!(config.seeds.is_empty());
158 }
159}