unistore_core/
capability.rs

1//! Capability trait 定义
2//!
3//! 所有能力模块必须实现此 trait,它是能力层的核心契约。
4
5use async_trait::async_trait;
6
7use crate::error::CapabilityError;
8use crate::info::CapabilityInfo;
9
10/// 能力 trait - 所有扩展能力的共同契约
11///
12/// 每个能力模块(如 serial、http、sqlite)都必须实现此 trait。
13/// 它定义了能力的生命周期、元数据和健康检查接口。
14///
15/// # 生命周期
16///
17/// ```text
18/// ┌───────────────────────────────────────────────────────────┐
19/// │  Created ──► start() ──► Running ──► stop() ──► Stopped  │
20/// │              │                        │                   │
21/// │              ▼                        ▼                   │
22/// │           StartError              StopError               │
23/// └───────────────────────────────────────────────────────────┘
24/// ```
25///
26/// # 实现示例
27///
28/// ```ignore
29/// use unistore_core::{Capability, CapabilityInfo, CapabilityError};
30/// use async_trait::async_trait;
31///
32/// pub struct SerialCapability {
33///     config: SerialConfig,
34/// }
35///
36/// #[async_trait]
37/// impl Capability for SerialCapability {
38///     fn info(&self) -> CapabilityInfo {
39///         CapabilityInfo::new("serial", env!("CARGO_PKG_VERSION"))
40///             .with_description("Serial port communication capability")
41///     }
42///
43///     async fn start(&mut self) -> Result<(), CapabilityError> {
44///         // 初始化串口资源
45///         Ok(())
46///     }
47///
48///     async fn stop(&mut self) -> Result<(), CapabilityError> {
49///         // 关闭所有串口连接
50///         Ok(())
51///     }
52///
53///     async fn health_check(&self) -> Result<(), CapabilityError> {
54///         // 检查能力状态
55///         Ok(())
56///     }
57/// }
58/// ```
59#[async_trait]
60pub trait Capability: Send + Sync {
61    /// 获取能力的元数据信息
62    ///
63    /// 返回能力的名称、版本、描述等信息。
64    /// 此方法应该是纯函数,不应有副作用。
65    fn info(&self) -> CapabilityInfo;
66
67    /// 启动能力
68    ///
69    /// 在此方法中初始化能力所需的资源,如:
70    /// - 建立连接
71    /// - 启动后台任务
72    /// - 加载配置
73    ///
74    /// # 错误
75    ///
76    /// 如果初始化失败,返回 `CapabilityError::StartFailed`。
77    async fn start(&mut self) -> Result<(), CapabilityError>;
78
79    /// 停止能力
80    ///
81    /// 在此方法中清理能力占用的资源,如:
82    /// - 关闭连接
83    /// - 取消后台任务
84    /// - 刷新缓冲区
85    ///
86    /// # 错误
87    ///
88    /// 如果清理失败,返回 `CapabilityError::StopFailed`。
89    /// 即使返回错误,运行时也会继续停止其他能力。
90    async fn stop(&mut self) -> Result<(), CapabilityError>;
91
92    /// 健康检查
93    ///
94    /// 检查能力是否正常工作。默认实现返回 Ok。
95    ///
96    /// # 用途
97    ///
98    /// - 运行时定期调用,检测能力健康状态
99    /// - 用于负载均衡和故障转移决策
100    ///
101    /// # 错误
102    ///
103    /// 如果能力不健康,返回 `CapabilityError::Unhealthy`。
104    async fn health_check(&self) -> Result<(), CapabilityError> {
105        Ok(())
106    }
107
108    /// 能力是否支持热重载
109    ///
110    /// 如果返回 `true`,运行时可以在不停止其他能力的情况下
111    /// 重新加载此能力的配置或实现。
112    ///
113    /// 默认返回 `false`。
114    fn supports_hot_reload(&self) -> bool {
115        false
116    }
117
118    /// 能力的依赖列表
119    ///
120    /// 返回此能力依赖的其他能力名称列表。
121    /// 运行时会确保依赖的能力先于此能力启动。
122    ///
123    /// 默认返回空列表(无依赖)。
124    fn dependencies(&self) -> Vec<&'static str> {
125        vec![]
126    }
127}
128
129/// 类型擦除的能力盒子
130///
131/// 用于在运行时存储和管理不同类型的能力实例。
132pub type BoxedCapability = Box<dyn Capability>;
133
134#[cfg(test)]
135mod tests {
136    use super::*;
137
138    struct TestCapability {
139        started: bool,
140    }
141
142    #[async_trait]
143    impl Capability for TestCapability {
144        fn info(&self) -> CapabilityInfo {
145            CapabilityInfo::new("test", "0.1.0")
146        }
147
148        async fn start(&mut self) -> Result<(), CapabilityError> {
149            self.started = true;
150            Ok(())
151        }
152
153        async fn stop(&mut self) -> Result<(), CapabilityError> {
154            self.started = false;
155            Ok(())
156        }
157    }
158
159    #[tokio::test]
160    async fn test_capability_lifecycle() {
161        let mut cap = TestCapability { started: false };
162        assert!(!cap.started);
163
164        cap.start().await.unwrap();
165        assert!(cap.started);
166
167        cap.stop().await.unwrap();
168        assert!(!cap.started);
169    }
170}