use std::time::Duration;
use crate::Endpoint;
#[derive(Debug, Clone, Default)]
pub struct DhtStats {
pub total_registrations: usize,
pub unique_keys: usize,
pub unique_trust_roots: usize,
pub max_registrations_per_key: usize,
pub avg_registrations_per_key: f64,
pub path_depth_histogram: Vec<usize>,
pub memory_bytes: usize,
}
impl DhtStats {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub const fn total_registrations(&self) -> usize {
self.total_registrations
}
#[must_use]
pub const fn unique_keys(&self) -> usize {
self.unique_keys
}
#[must_use]
pub const fn unique_trust_roots(&self) -> usize {
self.unique_trust_roots
}
#[must_use]
pub const fn max_registrations_per_key(&self) -> usize {
self.max_registrations_per_key
}
#[must_use]
pub const fn avg_registrations_per_key(&self) -> f64 {
self.avg_registrations_per_key
}
#[must_use]
pub const fn memory_bytes(&self) -> usize {
self.memory_bytes
}
}
#[derive(Debug, Clone)]
pub struct MigrationResult {
pub agent_uri: String,
pub old_endpoints: Vec<Endpoint>,
pub new_endpoints: Vec<Endpoint>,
pub update_latency: Duration,
pub success: bool,
}
impl MigrationResult {
#[must_use]
pub fn success(
agent_uri: impl Into<String>,
old_endpoints: Vec<Endpoint>,
new_endpoints: Vec<Endpoint>,
update_latency: Duration,
) -> Self {
Self {
agent_uri: agent_uri.into(),
old_endpoints,
new_endpoints,
update_latency,
success: true,
}
}
#[must_use]
pub fn failure(
agent_uri: impl Into<String>,
old_endpoints: Vec<Endpoint>,
new_endpoints: Vec<Endpoint>,
update_latency: Duration,
) -> Self {
Self {
agent_uri: agent_uri.into(),
old_endpoints,
new_endpoints,
update_latency,
success: false,
}
}
#[must_use]
pub const fn is_success(&self) -> bool {
self.success
}
#[must_use]
pub fn agent_uri(&self) -> &str {
&self.agent_uri
}
#[must_use]
pub fn old_endpoints(&self) -> &[Endpoint] {
&self.old_endpoints
}
#[must_use]
pub fn new_endpoints(&self) -> &[Endpoint] {
&self.new_endpoints
}
#[must_use]
pub const fn update_latency(&self) -> Duration {
self.update_latency
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_stats() {
let stats = DhtStats::default();
assert_eq!(stats.total_registrations(), 0);
assert_eq!(stats.unique_keys(), 0);
assert_eq!(stats.unique_trust_roots(), 0);
assert_eq!(stats.max_registrations_per_key(), 0);
assert!(
(stats.avg_registrations_per_key() - 0.0).abs() < f64::EPSILON,
"avg_registrations_per_key should be 0.0"
);
assert_eq!(stats.memory_bytes(), 0);
}
#[test]
fn successful_migration() {
let old = vec![Endpoint::https("old.example.com")];
let new = vec![Endpoint::https("new.example.com")];
let result = MigrationResult::success(
"agent://example.com/test/agent_123",
old.clone(),
new.clone(),
Duration::from_millis(50),
);
assert!(result.is_success());
assert_eq!(result.agent_uri(), "agent://example.com/test/agent_123");
assert_eq!(result.old_endpoints(), &old);
assert_eq!(result.new_endpoints(), &new);
assert_eq!(result.update_latency(), Duration::from_millis(50));
}
#[test]
fn failed_migration() {
let old = vec![Endpoint::https("old.example.com")];
let new = vec![Endpoint::https("new.example.com")];
let result = MigrationResult::failure(
"agent://example.com/test/agent_123",
old,
new,
Duration::from_millis(100),
);
assert!(!result.is_success());
}
}