1use 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
16pub struct PluginService {
22 registry: Arc<PluginRegistry>,
24 configs: Arc<RwLock<HashMap<String, serde_json::Value>>>,
26 statuses: Arc<RwLock<HashMap<String, PluginStatus>>>,
28}
29
30impl PluginService {
31 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 pub fn from_global() -> Self {
45 use std::sync::Arc;
46 Self::new(Arc::new(PluginRegistry::new()))
48 }
49
50 pub fn with_registry(registry: Arc<PluginRegistry>) -> Self {
52 Self::new(registry)
53 }
54
55 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 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 pub async fn invoke(
82 &self,
83 key: &str,
84 method: &str,
85 params: serde_json::Value,
86 ) -> PluginResult<serde_json::Value> {
87 self.check_status(key)?;
89
90 self.registry.invoke(key, method, params).await
92 }
93
94 pub fn get_instance(&self, key: &str) -> PluginResult<PluginHandle> {
100 self.check_status(key)?;
102
103 self.registry
104 .get(key)
105 .ok_or_else(|| PluginError::NotFound(key.to_string()))
106 }
107
108 pub fn check_status(&self, key: &str) -> PluginResult<()> {
112 if !self.registry.contains(key) {
114 return Err(PluginError::NotFound(key.to_string()));
115 }
116
117 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 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 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 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 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 pub fn list(&self) -> Vec<PluginInfo> {
163 self.registry.list()
164 }
165
166 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 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 pub fn remove(&self, key: &str) -> PluginResult<()> {
190 self.registry.remove(key);
192
193 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
210static GLOBAL_PLUGIN_SERVICE: once_cell::sync::Lazy<PluginService> =
212 once_cell::sync::Lazy::new(PluginService::from_global);
213
214pub fn global_plugin_service() -> &'static PluginService {
216 &GLOBAL_PLUGIN_SERVICE
217}