Skip to main content

cool_plugin/
service.rs

1//! 插件服务
2//!
3//! 对应 TypeScript 版本的 `plugin/service/info.ts`
4//!
5//! 提供插件管理、调用、状态检查等功能
6
7use crate::plugin::{Plugin, PluginError, PluginInfo, PluginResult, PluginStatus};
8use crate::registry::PluginRegistry;
9use parking_lot::RwLock;
10use std::collections::HashMap;
11use std::sync::Arc;
12use tokio::sync::Mutex;
13
14type PluginHandle = Arc<Mutex<Box<dyn Plugin>>>;
15
16/// 插件服务
17///
18/// 提供插件的管理、调用、状态检查等功能
19///
20/// 对应 TypeScript 版本的 `PluginService`
21pub struct PluginService {
22    /// 插件注册表
23    registry: Arc<PluginRegistry>,
24    /// 插件配置(key -> config)
25    configs: Arc<RwLock<HashMap<String, serde_json::Value>>>,
26    /// 插件状态(key -> status)
27    statuses: Arc<RwLock<HashMap<String, PluginStatus>>>,
28}
29
30impl PluginService {
31    /// 创建插件服务
32    pub fn new(registry: Arc<PluginRegistry>) -> Self {
33        Self {
34            registry,
35            configs: Arc::new(RwLock::new(HashMap::new())),
36            statuses: Arc::new(RwLock::new(HashMap::new())),
37        }
38    }
39
40    /// 从全局注册表创建插件服务
41    ///
42    /// 注意:由于 Rust 的所有权模型,这里创建一个新的服务实例,
43    /// 但会使用全局注册表。实际使用时,建议通过依赖注入传递同一个注册表实例。
44    pub fn from_global() -> Self {
45        use std::sync::Arc;
46        // 创建一个新的注册表,实际使用时应该通过依赖注入共享同一个注册表
47        Self::new(Arc::new(PluginRegistry::new()))
48    }
49
50    /// 使用指定的注册表创建插件服务
51    pub fn with_registry(registry: Arc<PluginRegistry>) -> Self {
52        Self::new(registry)
53    }
54
55    /// 获取插件配置
56    ///
57    /// 对应 TypeScript 版本的 `getConfig`
58    pub fn get_config(&self, key: &str) -> Option<serde_json::Value> {
59        let configs = self.configs.read();
60        configs.get(key).cloned()
61    }
62
63    /// 设置插件配置
64    pub fn set_config(&self, key: &str, config: serde_json::Value) {
65        let mut configs = self.configs.write();
66        configs.insert(key.to_string(), config);
67    }
68
69    /// 调用插件方法
70    ///
71    /// 对应 TypeScript 版本的 `invoke`
72    ///
73    /// # 示例
74    ///
75    /// ```rust,ignore
76    /// let service = PluginService::from_global();
77    /// let result = service.invoke("upload", "upload", json!({
78    ///     "file": "..."
79    /// })).await?;
80    /// ```
81    pub async fn invoke(
82        &self,
83        key: &str,
84        method: &str,
85        params: serde_json::Value,
86    ) -> PluginResult<serde_json::Value> {
87        // 检查插件状态
88        self.check_status(key)?;
89
90        // 从注册表获取插件并调用
91        self.registry.invoke(key, method, params).await
92    }
93
94    /// 获取插件实例
95    ///
96    /// 对应 TypeScript 版本的 `getInstance`
97    ///
98    /// 注意:由于 Rust 的类型系统限制,这里返回的是插件的 Arc 引用
99    pub fn get_instance(&self, key: &str) -> PluginResult<PluginHandle> {
100        // 检查插件状态
101        self.check_status(key)?;
102
103        self.registry
104            .get(key)
105            .ok_or_else(|| PluginError::NotFound(key.to_string()))
106    }
107
108    /// 检查插件状态
109    ///
110    /// 对应 TypeScript 版本的 `checkStatus`
111    pub fn check_status(&self, key: &str) -> PluginResult<()> {
112        // 先检查注册表中是否存在
113        if !self.registry.contains(key) {
114            return Err(PluginError::NotFound(key.to_string()));
115        }
116
117        // 检查状态
118        let statuses = self.statuses.read();
119        if let Some(status) = statuses.get(key) {
120            if *status == PluginStatus::Disabled {
121                return Err(PluginError::Disabled(key.to_string()));
122            }
123        }
124
125        Ok(())
126    }
127
128    /// 设置插件状态
129    pub fn set_status(&self, key: &str, status: PluginStatus) {
130        let mut statuses = self.statuses.write();
131        statuses.insert(key.to_string(), status);
132    }
133
134    /// 启用插件
135    pub fn enable(&self, key: &str) -> PluginResult<()> {
136        if !self.registry.contains(key) {
137            return Err(PluginError::NotFound(key.to_string()));
138        }
139        self.set_status(key, PluginStatus::Enabled);
140        Ok(())
141    }
142
143    /// 禁用插件
144    pub fn disable(&self, key: &str) -> PluginResult<()> {
145        if !self.registry.contains(key) {
146            return Err(PluginError::NotFound(key.to_string()));
147        }
148        self.set_status(key, PluginStatus::Disabled);
149        Ok(())
150    }
151
152    /// 获取插件信息
153    pub fn get_info(&self, key: &str) -> PluginResult<PluginInfo> {
154        let plugin = self.get_instance(key)?;
155        let plugin = plugin.blocking_lock();
156        Ok(plugin.info())
157    }
158
159    /// 获取所有插件信息
160    ///
161    /// 对应 TypeScript 版本的 `list`
162    pub fn list(&self) -> Vec<PluginInfo> {
163        self.registry.list()
164    }
165
166    /// 获取指定钩子类型的插件
167    pub fn get_by_hook(&self, hook: &str) -> Vec<PluginInfo> {
168        let plugins = self.registry.get_by_hook(hook);
169        plugins.iter().map(|p| p.blocking_lock().info()).collect()
170    }
171
172    /// 重新初始化插件
173    ///
174    /// 对应 TypeScript 版本的 `reInit`
175    pub async fn re_init(&self, key: &str) -> PluginResult<()> {
176        let plugin = self.get_instance(key)?;
177        let config = self.get_config(key).unwrap_or_default();
178
179        let mut plugin = plugin.lock().await;
180        plugin.init(config).await?;
181        plugin.ready().await?;
182
183        Ok(())
184    }
185
186    /// 移除插件
187    ///
188    /// 对应 TypeScript 版本的 `remove`
189    pub fn remove(&self, key: &str) -> PluginResult<()> {
190        // 从注册表移除
191        self.registry.remove(key);
192
193        // 清理配置和状态
194        let mut configs = self.configs.write();
195        configs.remove(key);
196
197        let mut statuses = self.statuses.write();
198        statuses.remove(key);
199
200        Ok(())
201    }
202}
203
204impl Default for PluginService {
205    fn default() -> Self {
206        Self::from_global()
207    }
208}
209
210/// 全局插件服务
211static GLOBAL_PLUGIN_SERVICE: once_cell::sync::Lazy<PluginService> =
212    once_cell::sync::Lazy::new(PluginService::from_global);
213
214/// 获取全局插件服务
215pub fn global_plugin_service() -> &'static PluginService {
216    &GLOBAL_PLUGIN_SERVICE
217}