use crate::plugin::{Plugin, PluginError, PluginInfo, PluginResult, PluginStatus};
use parking_lot::RwLock;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::Mutex;
type PluginHandle = Arc<Mutex<Box<dyn Plugin>>>;
type PluginMap = HashMap<String, PluginHandle>;
pub struct PluginRegistry {
plugins: RwLock<PluginMap>,
}
impl PluginRegistry {
pub fn new() -> Self {
Self {
plugins: RwLock::new(HashMap::new()),
}
}
pub fn register<P: Plugin + 'static>(&self, plugin: P) {
let info = plugin.info();
let key = info.key.clone();
let mut plugins = self.plugins.write();
plugins.insert(key.clone(), Arc::new(Mutex::new(Box::new(plugin))));
tracing::info!("插件已注册: {} ({})", info.name, key);
}
pub fn get(&self, key: &str) -> Option<PluginHandle> {
let plugins = self.plugins.read();
plugins.get(key).cloned()
}
pub fn remove(&self, key: &str) -> Option<PluginHandle> {
let mut plugins = self.plugins.write();
plugins.remove(key)
}
pub fn contains(&self, key: &str) -> bool {
let plugins = self.plugins.read();
plugins.contains_key(key)
}
pub fn list(&self) -> Vec<PluginInfo> {
let plugins = self.plugins.read();
plugins.values().map(|p| p.blocking_lock().info()).collect()
}
pub fn get_by_hook(&self, hook: &str) -> Vec<PluginHandle> {
let plugins = self.plugins.read();
plugins
.values()
.filter(|p| p.blocking_lock().info().hook == hook)
.cloned()
.collect()
}
pub async fn init_all(&self, configs: HashMap<String, serde_json::Value>) -> PluginResult<()> {
let plugins: Vec<_> = {
let plugins = self.plugins.read();
plugins.values().cloned().collect()
};
for plugin in plugins {
let key = plugin.blocking_lock().info().key.clone();
let config = configs.get(&key).cloned().unwrap_or_default();
let mut plugin = plugin.lock().await;
plugin.init(config).await?;
}
Ok(())
}
pub async fn ready_all(&self) -> PluginResult<()> {
let plugins: Vec<_> = {
let plugins = self.plugins.read();
plugins.values().cloned().collect()
};
for plugin in plugins {
let mut plugin = plugin.lock().await;
plugin.ready().await?;
}
Ok(())
}
pub async fn destroy_all(&self) -> PluginResult<()> {
let plugins: Vec<_> = {
let plugins = self.plugins.read();
plugins.values().cloned().collect()
};
for plugin in plugins.into_iter().rev() {
let mut plugin = plugin.lock().await;
plugin.destroy().await?;
}
Ok(())
}
pub async fn invoke(
&self,
key: &str,
method: &str,
params: serde_json::Value,
) -> PluginResult<serde_json::Value> {
let plugin = self
.get(key)
.ok_or_else(|| PluginError::NotFound(key.to_string()))?;
let plugin = plugin.lock().await;
if plugin.status() == PluginStatus::Disabled {
return Err(PluginError::Disabled(key.to_string()));
}
plugin.invoke(method, params).await
}
}
impl Default for PluginRegistry {
fn default() -> Self {
Self::new()
}
}
static GLOBAL_PLUGIN_REGISTRY: once_cell::sync::Lazy<PluginRegistry> =
once_cell::sync::Lazy::new(PluginRegistry::new);
pub fn global_plugin_registry() -> &'static PluginRegistry {
&GLOBAL_PLUGIN_REGISTRY
}