1use std::time::Duration;
4
5use crate::Endpoint;
6
7#[derive(Debug, Clone, Default)]
11pub struct DhtStats {
12 pub total_registrations: usize,
14 pub unique_keys: usize,
16 pub unique_trust_roots: usize,
18 pub max_registrations_per_key: usize,
28 pub avg_registrations_per_key: f64,
30 pub path_depth_histogram: Vec<usize>,
32 pub memory_bytes: usize,
34}
35
36impl DhtStats {
37 #[must_use]
39 pub fn new() -> Self {
40 Self::default()
41 }
42
43 #[must_use]
45 pub const fn total_registrations(&self) -> usize {
46 self.total_registrations
47 }
48
49 #[must_use]
51 pub const fn unique_keys(&self) -> usize {
52 self.unique_keys
53 }
54
55 #[must_use]
57 pub const fn unique_trust_roots(&self) -> usize {
58 self.unique_trust_roots
59 }
60
61 #[must_use]
66 pub const fn max_registrations_per_key(&self) -> usize {
67 self.max_registrations_per_key
68 }
69
70 #[must_use]
72 pub const fn avg_registrations_per_key(&self) -> f64 {
73 self.avg_registrations_per_key
74 }
75
76 #[must_use]
78 pub const fn memory_bytes(&self) -> usize {
79 self.memory_bytes
80 }
81}
82
83#[derive(Debug, Clone)]
87pub struct MigrationResult {
88 pub agent_uri: String,
90 pub old_endpoints: Vec<Endpoint>,
92 pub new_endpoints: Vec<Endpoint>,
94 pub update_latency: Duration,
96 pub success: bool,
98}
99
100impl MigrationResult {
101 #[must_use]
103 pub fn success(
104 agent_uri: impl Into<String>,
105 old_endpoints: Vec<Endpoint>,
106 new_endpoints: Vec<Endpoint>,
107 update_latency: Duration,
108 ) -> Self {
109 Self {
110 agent_uri: agent_uri.into(),
111 old_endpoints,
112 new_endpoints,
113 update_latency,
114 success: true,
115 }
116 }
117
118 #[must_use]
120 pub const fn is_success(&self) -> bool {
121 self.success
122 }
123
124 #[must_use]
126 pub fn agent_uri(&self) -> &str {
127 &self.agent_uri
128 }
129
130 #[must_use]
132 pub fn old_endpoints(&self) -> &[Endpoint] {
133 &self.old_endpoints
134 }
135
136 #[must_use]
138 pub fn new_endpoints(&self) -> &[Endpoint] {
139 &self.new_endpoints
140 }
141
142 #[must_use]
144 pub const fn update_latency(&self) -> Duration {
145 self.update_latency
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152
153 #[test]
154 fn default_stats() {
155 let stats = DhtStats::default();
156 assert_eq!(stats.total_registrations(), 0);
157 assert_eq!(stats.unique_keys(), 0);
158 assert_eq!(stats.unique_trust_roots(), 0);
159 assert_eq!(stats.max_registrations_per_key(), 0);
160 assert!(
161 (stats.avg_registrations_per_key() - 0.0).abs() < f64::EPSILON,
162 "avg_registrations_per_key should be 0.0"
163 );
164 assert_eq!(stats.memory_bytes(), 0);
165 }
166
167 #[test]
168 fn successful_migration() {
169 let old = vec![Endpoint::https("old.example.com")];
170 let new = vec![Endpoint::https("new.example.com")];
171 let result = MigrationResult::success(
172 "agent://example.com/test/agent_123",
173 old.clone(),
174 new.clone(),
175 Duration::from_millis(50),
176 );
177
178 assert!(result.is_success());
179 assert_eq!(result.agent_uri(), "agent://example.com/test/agent_123");
180 assert_eq!(result.old_endpoints(), &old);
181 assert_eq!(result.new_endpoints(), &new);
182 assert_eq!(result.update_latency(), Duration::from_millis(50));
183 }
184}