openlark_client/registry/
mod.rs1use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7use thiserror::Error;
8
9pub(crate) mod bootstrap;
10
11#[derive(Error, Debug, Clone)]
13pub enum RegistryError {
14 #[error("服务 '{name}' 已存在")]
18 ServiceAlreadyExists {
19 name: String,
21 },
22
23 #[error("服务 '{name}' 不存在")]
27 ServiceNotFound {
28 name: String,
30 },
31
32 #[error("循环依赖检测: {dependency_chain}")]
36 CircularDependency {
37 dependency_chain: String,
39 },
40
41 #[error("缺少依赖服务: {missing_dependencies:?}")]
45 MissingDependencies {
46 missing_dependencies: Vec<String>,
48 },
49
50 #[error("功能标志 '{flag}' 无效")]
54 InvalidFeatureFlag {
55 flag: String,
57 },
58}
59
60pub type RegistryResult<T> = Result<T, RegistryError>;
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct ServiceMetadata {
66 pub name: String,
68 pub version: String,
70 pub description: Option<String>,
72 pub dependencies: Vec<String>,
74 pub provides: Vec<String>,
76 pub status: ServiceStatus,
78 pub priority: u32,
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
84pub enum ServiceStatus {
85 Uninitialized,
87 Initializing,
89 Ready,
91 Running,
93 Stopped,
95 Error(String),
97}
98
99#[derive(Debug)]
101pub struct ServiceEntry {
102 pub metadata: ServiceMetadata,
104 pub instance: Option<Box<dyn std::any::Any + Send + Sync>>,
106 pub created_at: chrono::DateTime<chrono::Utc>,
108 pub updated_at: chrono::DateTime<chrono::Utc>,
110}
111
112pub trait ServiceRegistry: Send + Sync {
114 fn register_service(&mut self, metadata: ServiceMetadata) -> RegistryResult<()>;
116
117 fn unregister_service(&mut self, name: &str) -> RegistryResult<()>;
119
120 fn get_service(&self, name: &str) -> RegistryResult<&ServiceEntry>;
122
123 fn get_service_typed<T>(&self, name: &str) -> RegistryResult<&T>
125 where
126 T: 'static;
127
128 fn list_services(&self) -> Vec<&ServiceEntry>;
130
131 fn has_service(&self, name: &str) -> bool;
133
134 fn update_service_status(&mut self, name: &str, status: ServiceStatus) -> RegistryResult<()>;
136
137 fn get_dependency_graph(&self) -> HashMap<String, Vec<String>>;
139}
140
141#[derive(Debug)]
143pub struct DefaultServiceRegistry {
144 services: HashMap<String, ServiceEntry>,
146}
147
148impl Default for DefaultServiceRegistry {
149 fn default() -> Self {
150 Self::new()
151 }
152}
153
154impl DefaultServiceRegistry {
155 pub fn new() -> Self {
157 Self {
158 services: HashMap::new(),
159 }
160 }
161}
162
163impl ServiceRegistry for DefaultServiceRegistry {
164 fn register_service(&mut self, metadata: ServiceMetadata) -> RegistryResult<()> {
165 if self.services.contains_key(&metadata.name) {
167 return Err(RegistryError::ServiceAlreadyExists {
168 name: metadata.name,
169 });
170 }
171
172 let entry = ServiceEntry {
174 metadata: metadata.clone(),
175 instance: None,
176 created_at: chrono::Utc::now(),
177 updated_at: chrono::Utc::now(),
178 };
179
180 self.services.insert(metadata.name.clone(), entry);
182
183 Ok(())
184 }
185
186 fn unregister_service(&mut self, name: &str) -> RegistryResult<()> {
187 if !self.services.contains_key(name) {
188 return Err(RegistryError::ServiceNotFound {
189 name: name.to_string(),
190 });
191 }
192
193 self.services.remove(name);
194 Ok(())
195 }
196
197 fn get_service(&self, name: &str) -> RegistryResult<&ServiceEntry> {
198 self.services
199 .get(name)
200 .ok_or_else(|| RegistryError::ServiceNotFound {
201 name: name.to_string(),
202 })
203 }
204
205 fn get_service_typed<T>(&self, name: &str) -> RegistryResult<&T>
206 where
207 T: 'static,
208 {
209 let entry = self.get_service(name)?;
210
211 entry
212 .instance
213 .as_ref()
214 .and_then(|instance| instance.downcast_ref::<T>())
215 .ok_or_else(|| RegistryError::ServiceNotFound {
216 name: format!("类型转换失败: {}", name),
217 })
218 }
219
220 fn list_services(&self) -> Vec<&ServiceEntry> {
221 self.services.values().collect()
222 }
223
224 fn has_service(&self, name: &str) -> bool {
225 self.services.contains_key(name)
226 }
227
228 fn update_service_status(&mut self, name: &str, status: ServiceStatus) -> RegistryResult<()> {
229 let entry = self
230 .services
231 .get_mut(name)
232 .ok_or_else(|| RegistryError::ServiceNotFound {
233 name: name.to_string(),
234 })?;
235
236 entry.metadata.status = status.clone();
237 entry.updated_at = chrono::Utc::now();
238
239 Ok(())
240 }
241
242 fn get_dependency_graph(&self) -> HashMap<String, Vec<String>> {
243 self.services
244 .iter()
245 .map(|(name, entry)| (name.clone(), entry.metadata.dependencies.clone()))
246 .collect()
247 }
248}
249
250#[cfg(test)]
251#[allow(unused_imports)]
252mod tests {
253 use super::*;
254
255 #[test]
256 fn test_service_registration() {
257 let mut registry = DefaultServiceRegistry::new();
258
259 let metadata = ServiceMetadata {
260 name: "test-service".to_string(),
261 version: "1.0.0".to_string(),
262 description: Some("测试服务".to_string()),
263 dependencies: vec![],
264 provides: vec!["test-feature".to_string()],
265 status: ServiceStatus::Uninitialized,
266 priority: 1,
267 };
268
269 assert!(registry.register_service(metadata).is_ok());
270 assert!(registry.has_service("test-service"));
271 }
272
273 #[test]
274 fn test_duplicate_registration() {
275 let mut registry = DefaultServiceRegistry::new();
276
277 let metadata = ServiceMetadata {
278 name: "test-service".to_string(),
279 version: "1.0.0".to_string(),
280 description: None,
281 dependencies: vec![],
282 provides: vec![],
283 status: ServiceStatus::Uninitialized,
284 priority: 1,
285 };
286
287 registry.register_service(metadata.clone()).unwrap();
288
289 let result = registry.register_service(metadata);
290 assert!(matches!(
291 result,
292 Err(RegistryError::ServiceAlreadyExists { .. })
293 ));
294 }
295}