flare_core_runtime/plugin/
manager.rs1use super::{Plugin, PluginContext};
6use crate::error::PluginError;
7use std::sync::Arc;
8use tracing::{error, warn};
9
10pub struct PluginManager {
26 plugins: Vec<Arc<dyn Plugin>>,
27}
28
29impl PluginManager {
30 pub fn new() -> Self {
32 Self {
33 plugins: Vec::new(),
34 }
35 }
36
37 pub fn register(&mut self, plugin: Arc<dyn Plugin>) {
43 let name = plugin.name().to_string();
44 self.plugins.push(plugin);
45 tracing::debug!(plugin_name = %name, "Plugin registered");
46 }
47
48 pub async fn on_startup(&self, ctx: &PluginContext) -> Result<(), PluginError> {
52 for plugin in &self.plugins {
53 if let Err(e) = plugin.on_startup(ctx).await {
54 error!(
55 plugin_name = %plugin.name(),
56 error = %e,
57 "Plugin on_startup failed"
58 );
59 }
61 }
62 Ok(())
63 }
64
65 pub async fn on_task_start(&self, ctx: &PluginContext) -> Result<(), PluginError> {
69 for plugin in &self.plugins {
70 if let Err(e) = plugin.on_task_start(ctx).await {
71 warn!(
72 plugin_name = %plugin.name(),
73 error = %e,
74 "Plugin on_task_start failed"
75 );
76 }
77 }
78 Ok(())
79 }
80
81 pub async fn on_task_stop(&self, ctx: &PluginContext) -> Result<(), PluginError> {
85 for plugin in &self.plugins {
86 if let Err(e) = plugin.on_task_stop(ctx).await {
87 warn!(
88 plugin_name = %plugin.name(),
89 error = %e,
90 "Plugin on_task_stop failed"
91 );
92 }
93 }
94 Ok(())
95 }
96
97 pub async fn on_shutdown(&self, ctx: &PluginContext) -> Result<(), PluginError> {
101 for plugin in &self.plugins {
102 if let Err(e) = plugin.on_shutdown(ctx).await {
103 warn!(
104 plugin_name = %plugin.name(),
105 error = %e,
106 "Plugin on_shutdown failed"
107 );
108 }
109 }
110 Ok(())
111 }
112
113 pub async fn on_error(&self, ctx: &PluginContext, error: &str) -> Result<(), PluginError> {
117 for plugin in &self.plugins {
118 if let Err(e) = plugin.on_error(ctx, error).await {
119 warn!(
120 plugin_name = %plugin.name(),
121 error = %e,
122 "Plugin on_error failed"
123 );
124 }
125 }
126 Ok(())
127 }
128
129 pub fn plugin_count(&self) -> usize {
131 self.plugins.len()
132 }
133}
134
135impl Default for PluginManager {
136 fn default() -> Self {
137 Self::new()
138 }
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144 use crate::task::TaskState;
145
146 struct TestPlugin {
147 name: String,
148 }
149
150 impl Plugin for TestPlugin {
151 fn name(&self) -> &str {
152 &self.name
153 }
154 }
155
156 #[tokio::test]
157 async fn test_plugin_manager_register() {
158 let mut manager = PluginManager::new();
159 manager.register(Arc::new(TestPlugin {
160 name: "test-plugin".to_string(),
161 }));
162
163 assert_eq!(manager.plugin_count(), 1);
164 }
165
166 #[tokio::test]
167 async fn test_plugin_manager_on_startup() {
168 let mut manager = PluginManager::new();
169 manager.register(Arc::new(TestPlugin {
170 name: "test-plugin".to_string(),
171 }));
172
173 let ctx = PluginContext::new("test-runtime");
174 let result = manager.on_startup(&ctx).await;
175 assert!(result.is_ok());
176 }
177}