1use std::time::Duration;
5
6use crate::node_type::NodeType;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct RepNode {
15 pub name: String,
17 pub node_type: NodeType,
19 pub host: String,
21 pub port: u16,
23 pub node_id: u32,
25 pub read_capacity_pct: u32,
29 pub write_capacity_pct: u32,
31 pub latency_hint_ms: u64,
33}
34
35impl RepNode {
36 pub fn new(
40 name: String,
41 node_type: NodeType,
42 host: String,
43 port: u16,
44 node_id: u32,
45 ) -> Self {
46 Self {
47 name,
48 node_type,
49 host,
50 port,
51 node_id,
52 read_capacity_pct: 100,
53 write_capacity_pct: 100,
54 latency_hint_ms: 1,
55 }
56 }
57
58 pub fn with_read_capacity(mut self, cap: f64) -> Self {
62 self.read_capacity_pct = (cap * 100.0).round() as u32;
63 self
64 }
65
66 pub fn with_write_capacity(mut self, cap: f64) -> Self {
68 self.write_capacity_pct = (cap * 100.0).round() as u32;
69 self
70 }
71
72 pub fn with_latency_hint(mut self, d: Duration) -> Self {
74 self.latency_hint_ms = d.as_millis() as u64;
75 self
76 }
77
78 pub fn to_quoracle_node(&self) -> quoracle::Node<String> {
82 let read_cap = self.read_capacity_pct as f64 / 100.0;
83 let write_cap = self.write_capacity_pct as f64 / 100.0;
84 let latency = Duration::from_millis(self.latency_hint_ms);
85 quoracle::Node::new(self.name.clone())
86 .with_read_write_capacity(read_cap, write_cap)
87 .with_latency(latency)
88 }
89
90 pub fn name(&self) -> &str {
92 &self.name
93 }
94
95 pub fn node_type(&self) -> NodeType {
97 self.node_type
98 }
99
100 pub fn host(&self) -> &str {
102 &self.host
103 }
104
105 pub fn port(&self) -> u16 {
107 self.port
108 }
109
110 pub fn node_id(&self) -> u32 {
112 self.node_id
113 }
114
115 pub fn socket_address(&self) -> String {
117 format!("{}:{}", self.host, self.port)
118 }
119
120 pub fn is_electable(&self) -> bool {
122 self.node_type.is_electable()
123 }
124
125 pub fn is_data_node(&self) -> bool {
127 self.node_type.is_data_node()
128 }
129
130 pub fn can_be_master(&self) -> bool {
132 self.node_type.can_be_master()
133 }
134}
135
136impl std::fmt::Display for RepNode {
137 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
138 write!(
139 f,
140 "RepNode(name={}, type={}, addr={}, id={})",
141 self.name,
142 self.node_type,
143 self.socket_address(),
144 self.node_id
145 )
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152
153 fn make_node() -> RepNode {
154 RepNode::new(
155 "node1".to_string(),
156 NodeType::Electable,
157 "localhost".to_string(),
158 5001,
159 1,
160 )
161 }
162
163 #[test]
164 fn test_new_and_getters() {
165 let node = make_node();
166 assert_eq!(node.name(), "node1");
167 assert_eq!(node.node_type(), NodeType::Electable);
168 assert_eq!(node.host(), "localhost");
169 assert_eq!(node.port(), 5001);
170 assert_eq!(node.node_id(), 1);
171 }
172
173 #[test]
174 fn test_socket_address() {
175 let node = make_node();
176 assert_eq!(node.socket_address(), "localhost:5001");
177 }
178
179 #[test]
180 fn test_socket_address_with_ip() {
181 let node = RepNode::new(
182 "node2".to_string(),
183 NodeType::Secondary,
184 "192.168.1.100".to_string(),
185 6000,
186 2,
187 );
188 assert_eq!(node.socket_address(), "192.168.1.100:6000");
189 }
190
191 #[test]
192 fn test_delegation_methods() {
193 let electable = make_node();
194 assert!(electable.is_electable());
195 assert!(electable.is_data_node());
196 assert!(electable.can_be_master());
197
198 let monitor = RepNode::new(
199 "mon".to_string(),
200 NodeType::Monitor,
201 "localhost".to_string(),
202 5002,
203 2,
204 );
205 assert!(!monitor.is_electable());
206 assert!(!monitor.is_data_node());
207 assert!(!monitor.can_be_master());
208 }
209
210 #[test]
211 fn test_display() {
212 let node = make_node();
213 let s = node.to_string();
214 assert!(s.contains("node1"));
215 assert!(s.contains("ELECTABLE"));
216 assert!(s.contains("localhost:5001"));
217 assert!(s.contains("id=1"));
218 }
219
220 #[test]
221 fn test_clone_and_eq() {
222 let node = make_node();
223 let cloned = node.clone();
224 assert_eq!(node, cloned);
225 }
226
227 #[test]
228 fn test_not_equal() {
229 let node1 = make_node();
230 let node2 = RepNode::new(
231 "node2".to_string(),
232 NodeType::Electable,
233 "localhost".to_string(),
234 5001,
235 2,
236 );
237 assert_ne!(node1, node2);
238 }
239
240 #[test]
241 fn test_debug() {
242 let node = make_node();
243 let s = format!("{:?}", node);
244 assert!(s.contains("RepNode"));
245 assert!(s.contains("node1"));
246 }
247}