Skip to main content

mecha10_dev/services/discovery/
mod.rs

1#![allow(dead_code)]
2
3//! Discovery service for finding Mecha10 nodes on the network
4//!
5//! This service provides operations for discovering and monitoring Mecha10
6//! nodes through Redis pub/sub and network scanning.
7
8mod node_manager;
9mod parser;
10mod redis_ops;
11
12use anyhow::Result;
13use std::collections::HashMap;
14use std::time::{Duration, SystemTime};
15
16#[derive(Debug, Clone)]
17pub struct NodeInfo {
18    pub node_id: String,
19    pub node_type: String,
20    pub host: String,
21    pub port: u16,
22    pub last_seen: SystemTime,
23    pub metadata: HashMap<String, String>,
24}
25
26#[derive(Debug, Clone)]
27pub struct DiscoveryConfig {
28    pub redis_url: String,
29    pub discovery_topic: String,
30    pub heartbeat_interval: Duration,
31    pub node_timeout: Duration,
32    pub scan_subnet: Option<String>,
33}
34
35impl Default for DiscoveryConfig {
36    fn default() -> Self {
37        Self {
38            redis_url: "redis://localhost:6379".to_string(),
39            discovery_topic: "mecha10/discovery".to_string(),
40            heartbeat_interval: Duration::from_secs(5),
41            node_timeout: Duration::from_secs(30),
42            scan_subnet: None,
43        }
44    }
45}
46
47pub struct DiscoveryService {
48    discovered_nodes: HashMap<String, NodeInfo>,
49}
50
51impl DiscoveryService {
52    /// Create a new discovery service
53    pub fn new() -> Self {
54        Self {
55            discovered_nodes: HashMap::new(),
56        }
57    }
58
59    /// Discover active nodes on the network
60    ///
61    /// # Arguments
62    ///
63    /// * `config` - Discovery configuration
64    pub async fn discover(&mut self, config: &DiscoveryConfig) -> Result<Vec<NodeInfo>> {
65        redis_ops::discover(config, &mut self.discovered_nodes).await
66    }
67
68    /// Monitor for new nodes
69    ///
70    /// # Arguments
71    ///
72    /// * `config` - Discovery configuration
73    /// * `callback` - Function to call when a new node is discovered
74    pub async fn monitor<F>(&mut self, config: &DiscoveryConfig, callback: F) -> Result<()>
75    where
76        F: FnMut(&NodeInfo),
77    {
78        redis_ops::monitor(config, &mut self.discovered_nodes, callback).await
79    }
80
81    /// Get list of currently known nodes
82    pub fn get_nodes(&self) -> Vec<&NodeInfo> {
83        node_manager::get_nodes(&self.discovered_nodes)
84    }
85
86    /// Get a specific node by ID
87    ///
88    /// # Arguments
89    ///
90    /// * `node_id` - Node identifier
91    pub fn get_node(&self, node_id: &str) -> Option<&NodeInfo> {
92        node_manager::get_node(&self.discovered_nodes, node_id)
93    }
94
95    /// Remove stale nodes that haven't sent heartbeats
96    ///
97    /// # Arguments
98    ///
99    /// * `timeout` - Maximum time since last heartbeat
100    pub fn cleanup_stale_nodes(&mut self, timeout: Duration) -> usize {
101        node_manager::cleanup_stale_nodes(&mut self.discovered_nodes, timeout)
102    }
103
104    /// Broadcast presence announcement
105    ///
106    /// # Arguments
107    ///
108    /// * `config` - Discovery configuration
109    /// * `node_info` - Information about this node
110    pub async fn announce(&self, config: &DiscoveryConfig, node_info: &NodeInfo) -> Result<()> {
111        redis_ops::announce(config, node_info).await
112    }
113
114    /// Send heartbeat for a node
115    ///
116    /// # Arguments
117    ///
118    /// * `config` - Discovery configuration
119    /// * `node_id` - Node identifier
120    pub async fn heartbeat(&self, config: &DiscoveryConfig, node_id: &str) -> Result<()> {
121        redis_ops::heartbeat(config, node_id).await
122    }
123
124    /// Get node count
125    pub fn node_count(&self) -> usize {
126        node_manager::node_count(&self.discovered_nodes)
127    }
128
129    /// Get nodes by type
130    ///
131    /// # Arguments
132    ///
133    /// * `node_type` - Type of nodes to filter
134    pub fn get_nodes_by_type(&self, node_type: &str) -> Vec<&NodeInfo> {
135        node_manager::get_nodes_by_type(&self.discovered_nodes, node_type)
136    }
137
138    /// Clear all discovered nodes
139    pub fn clear(&mut self) {
140        node_manager::clear(&mut self.discovered_nodes);
141    }
142}
143
144impl Default for DiscoveryService {
145    fn default() -> Self {
146        Self::new()
147    }
148}