use super::{Plugin, PluginContext};
use crate::error::PluginError;
use std::sync::Arc;
use tracing::{error, warn};
pub struct PluginManager {
plugins: Vec<Arc<dyn Plugin>>,
}
impl PluginManager {
pub fn new() -> Self {
Self {
plugins: Vec::new(),
}
}
pub fn register(&mut self, plugin: Arc<dyn Plugin>) {
let name = plugin.name().to_string();
self.plugins.push(plugin);
tracing::debug!(plugin_name = %name, "Plugin registered");
}
pub async fn on_startup(&self, ctx: &PluginContext) -> Result<(), PluginError> {
for plugin in &self.plugins {
if let Err(e) = plugin.on_startup(ctx).await {
error!(
plugin_name = %plugin.name(),
error = %e,
"Plugin on_startup failed"
);
}
}
Ok(())
}
pub async fn on_task_start(&self, ctx: &PluginContext) -> Result<(), PluginError> {
for plugin in &self.plugins {
if let Err(e) = plugin.on_task_start(ctx).await {
warn!(
plugin_name = %plugin.name(),
error = %e,
"Plugin on_task_start failed"
);
}
}
Ok(())
}
pub async fn on_task_stop(&self, ctx: &PluginContext) -> Result<(), PluginError> {
for plugin in &self.plugins {
if let Err(e) = plugin.on_task_stop(ctx).await {
warn!(
plugin_name = %plugin.name(),
error = %e,
"Plugin on_task_stop failed"
);
}
}
Ok(())
}
pub async fn on_shutdown(&self, ctx: &PluginContext) -> Result<(), PluginError> {
for plugin in &self.plugins {
if let Err(e) = plugin.on_shutdown(ctx).await {
warn!(
plugin_name = %plugin.name(),
error = %e,
"Plugin on_shutdown failed"
);
}
}
Ok(())
}
pub async fn on_error(&self, ctx: &PluginContext, error: &str) -> Result<(), PluginError> {
for plugin in &self.plugins {
if let Err(e) = plugin.on_error(ctx, error).await {
warn!(
plugin_name = %plugin.name(),
error = %e,
"Plugin on_error failed"
);
}
}
Ok(())
}
pub fn plugin_count(&self) -> usize {
self.plugins.len()
}
}
impl Default for PluginManager {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::task::TaskState;
struct TestPlugin {
name: String,
}
impl Plugin for TestPlugin {
fn name(&self) -> &str {
&self.name
}
}
#[tokio::test]
async fn test_plugin_manager_register() {
let mut manager = PluginManager::new();
manager.register(Arc::new(TestPlugin {
name: "test-plugin".to_string(),
}));
assert_eq!(manager.plugin_count(), 1);
}
#[tokio::test]
async fn test_plugin_manager_on_startup() {
let mut manager = PluginManager::new();
manager.register(Arc::new(TestPlugin {
name: "test-plugin".to_string(),
}));
let ctx = PluginContext::new("test-runtime");
let result = manager.on_startup(&ctx).await;
assert!(result.is_ok());
}
}