cloud_disk_sync/plugins/
manager.rs

1use crate::error::Result;
2use crate::plugins::hooks::{HookContext, HookHandler, HookPriority, PluginHook};
3use async_trait::async_trait;
4// src/plugins/manager.rs
5use std::collections::HashMap;
6
7pub struct HookManager {
8    handlers: HashMap<String, Vec<Box<dyn HookHandler>>>,
9    hooks_by_priority: HashMap<PluginHook, Vec<Box<dyn HookHandler>>>,
10}
11
12impl HookManager {
13    pub fn new() -> Self {
14        Self {
15            handlers: HashMap::new(),
16            hooks_by_priority: HashMap::new(),
17        }
18    }
19
20    pub fn register_handler(&mut self, handler: Box<dyn HookHandler>) {
21        let handlers = self
22            .handlers
23            .entry("all".to_string())
24            .or_insert_with(Vec::new);
25        handlers.push(handler);
26    }
27
28    pub async fn execute_hook(&self, hook: PluginHook, context: &mut HookContext) -> Result<()> {
29        if let Some(handlers) = self.handlers.get("all") {
30            // 按优先级排序
31            let mut sorted_handlers: Vec<_> = handlers
32                .iter()
33                .map(|h| (h.get_priority(&hook), h.as_ref()))
34                .collect();
35
36            sorted_handlers.sort_by(|a, b| b.0.cmp(&a.0)); // 降序,高优先级先执行
37
38            for (_, handler) in sorted_handlers {
39                if handler.supports_hook(&hook) {
40                    handler.handle_hook(hook.clone(), context).await?;
41                }
42            }
43        }
44
45        Ok(())
46    }
47
48    fn all_hook_types() -> Vec<&'static str> {
49        vec!["all"]
50    }
51}
52
53/// 基础插件实现示例
54#[derive(Clone)]
55pub struct LoggingPlugin {
56    name: String,
57    version: String,
58    enabled: bool,
59}
60
61impl LoggingPlugin {
62    pub fn new() -> Self {
63        Self {
64            name: "LoggingPlugin".to_string(),
65            version: "1.0.0".to_string(),
66            enabled: true,
67        }
68    }
69}
70
71#[async_trait]
72impl crate::core::traits::Plugin for LoggingPlugin {
73    fn name(&self) -> &str {
74        &self.name
75    }
76
77    fn version(&self) -> &str {
78        &self.version
79    }
80
81    fn description(&self) -> &str {
82        "A plugin that logs all synchronization events"
83    }
84
85    async fn initialize(&self) -> Result<()> {
86        log::info!("LoggingPlugin initialized");
87        Ok(())
88    }
89
90    async fn shutdown(&self) -> Result<()> {
91        log::info!("LoggingPlugin shutting down");
92        Ok(())
93    }
94
95    fn hooks(&self) -> Vec<PluginHook> {
96        vec![
97            PluginHook::PreSync {
98                task_id: "*".to_string(),
99                priority: HookPriority::Normal,
100            },
101            PluginHook::PostSync {
102                task_id: "*".to_string(),
103                priority: HookPriority::Normal,
104            },
105            PluginHook::OnError {
106                priority: HookPriority::Normal,
107            },
108        ]
109    }
110}
111
112#[async_trait]
113impl HookHandler for LoggingPlugin {
114    async fn handle_hook(&self, hook: PluginHook, context: &mut HookContext) -> Result<()> {
115        if !self.enabled {
116            return Ok(());
117        }
118
119        match &hook {
120            PluginHook::PreSync { task_id, .. } => {
121                log::info!("Starting sync for task: {}", task_id);
122                if let Some(task) = &context.task {
123                    log::debug!("Task config: {:?}", task);
124                }
125            }
126            PluginHook::PostSync { task_id, .. } => {
127                log::info!("Completed sync for task: {}", task_id);
128                if let Some(report) = &context.report {
129                    log::debug!("Sync report: {:?}", report.statistics);
130                }
131            }
132            PluginHook::OnError { .. } => {
133                if let Some(error) = &context.error {
134                    log::error!("Sync error: {}", error);
135                }
136            }
137            _ => {
138                // 其他钩子不需要处理
139            }
140        }
141
142        Ok(())
143    }
144
145    fn supports_hook(&self, hook: &PluginHook) -> bool {
146        match hook {
147            PluginHook::PreSync { .. } => true,
148            PluginHook::PostSync { .. } => true,
149            PluginHook::OnError { .. } => true,
150            _ => false,
151        }
152    }
153
154    fn get_priority(&self, _hook: &PluginHook) -> HookPriority {
155        HookPriority::Normal
156    }
157}
158
159// 简化:不支持克隆 trait 对象,统一在 \"all\" 分组下执行