Regarding the issue of closure lifecycle, I'm seeking help from all the experts

⚓ Rust    📅 2025-04-30    👤 surdeus    👁️ 4      

surdeus

Warning

This post was published 113 days ago. The information described in this article may have changed.
use serde_json::Value;
use std::{cell::RefCell, collections::HashMap, rc::Rc};

pub struct Event {
    name: String,        // 事件名
    data: Option<Value>, // 数据使用Value格式
}
impl Event {
    pub fn new(name: &str, data: Option<Value>) -> Self {
        Self {
            name: name.to_string(),
            data,
        }
    }
}

// type EventListener = fn(Option<Value>);
type EventListener = Box<dyn FnMut(Option<Value>)>;
type ListenersMap = HashMap<String, Vec<EventListener>>;
struct EventDispatcher {
    listeners: ListenersMap,
}
impl EventDispatcher {
    pub fn new() -> Self {
        Self {
            listeners: HashMap::new(),
        }
    }
    pub fn dispatch_event(&mut self, event: Event) {
        if let Some(listeners) = self.listeners.get_mut(&event.name) {
            for listener in listeners {
                listener(event.data.clone());
            }
        }
    }
    pub fn add_event_listener(&mut self, name: &str, listener: EventListener) {
        let arr = self
            .listeners
            .entry(name.to_string())
            .or_insert_with(Vec::new);

        arr.push(listener);

        // let func = &(listener);
        // if !arr.contains(func) {
        //     arr.push(listener);
        // }
    }
    pub fn on(&mut self, name: &str, listener: EventListener) {
        self.add_event_listener(name, listener);
    }
    pub fn emit(&mut self, name: &str, params: Option<Value>) {
        self.dispatch_event(Event::new(name, params))
    }
}

trait PluginOptions {
    fn name(&self) -> &str;
    fn deps(&self) -> Vec<&str>;
    fn install(&mut self, engine: &mut Engine);
    fn dispose(&mut self, engine: &mut Engine);
}
trait StrategyOptions {
    fn name(&self) -> &str;
    fn condition(&self) -> Vec<&str>;
    fn exec(&self, engine: &mut Engine);
    fn rollback(&mut self, engine: &mut Engine);
}
type PluginsMap = HashMap<String, Box<dyn PluginOptions>>;
type StrategysMap = HashMap<String, Box<dyn StrategyOptions>>;
struct Engine {
    event: EventDispatcher,
    plugins: PluginsMap,
    strategys: StrategysMap,
}
impl Engine {
    pub fn new() -> Self {
        Self {
            event: EventDispatcher::new(),
            plugins: HashMap::new(),
            strategys: HashMap::new(),
        }
    }
    pub fn install<P: PluginOptions + 'static>(&mut self, plugin: P) -> String {
        let name = plugin.name();
        if !self.plugins.contains_key(name) {
            // 不存在对应的插件

            // 检查插件依赖
            let mut deps: Vec<&str> = Vec::new();
            for dep in plugin.deps() {
                // 依赖插件不存在
                if !self.plugins.contains_key(dep) {
                    deps.push(dep);
                }
            }
            if !deps.is_empty() {
                // 提示错误
                return format!(
                    "安装插件 '{}' 出错:依赖插件 '{}' 不存在",
                    name,
                    deps.join(",")
                );
            }

            // 执行插件安装方法
            let mut plugin_box = Box::new(plugin);
            plugin_box.install(self);

            // 记录插件
            self.plugins
                .insert(plugin_box.name().to_string(), plugin_box);
        }

        "".to_string()
    }
    pub fn uninstall(&mut self, plugin_name: &str) {
        if let Some(mut plugin) = self.plugins.remove(plugin_name) {
            // 策略B依赖插件A,插件A被卸载,关联的策略B也要被回滚
            let mut strategies = Vec::new();
            for (_, strategy) in self.strategys.iter() {
                if strategy.condition().contains(&plugin_name) {
                    strategies.push(strategy.name().to_string());
                }
            }
            // 执行回滚操作
            for strategy_name in strategies {
                self.rollback(&strategy_name);
            }

            // 插件B依赖插件A,插件A被卸载,关联的插件B也要被卸载
            let mut plugins = Vec::new();
            for (_, plugin) in self.plugins.iter() {
                if plugin.deps().contains(&plugin_name) {
                    plugins.push(plugin.name().to_string());
                }
            }
            // 执行关键插件的卸载
            for plugin_name in plugins {
                self.uninstall(&plugin_name);
            }

            // 执行销毁方法
            plugin.dispose(self);
        } else {
            println!("插件 {} 不存在", plugin_name)
        }
    }
    pub fn exec<S: StrategyOptions + 'static>(&mut self, strategy: S) -> String {
        let name = strategy.name();
        if !self.strategys.contains_key(name) {
            // 不存在对应的策略

            // 检查策略依赖
            let mut plugins: Vec<&str> = Vec::new();
            for plugin in strategy.condition() {
                // 依赖插件不存在,记录起来
                if !self.plugins.contains_key(plugin) {
                    plugins.push(plugin);
                }
            }
            if plugins.len() > 0 {
                // 提示错误
                return format!(
                    "执行策略 '{}' 出错:依赖插件 '{}' 不存在",
                    name,
                    plugins.join(",")
                );
            }

            // 执行策略
            strategy.exec(self);

            // 记录策略
            self.strategys
                .insert(strategy.name().to_string(), Box::new(strategy));
        }

        "".to_string()
    }
    pub fn rollback(&mut self, strategy_name: &str) {
        // 找到与name对应的策略并删除
        if let Some(mut strategy) = self.strategys.remove(strategy_name) {
            // 执行回滚方法
            strategy.rollback(self);
        } else {
            println!("策略 {} 不存在", strategy_name)
        }
    }
}

struct APlugin;
impl PluginOptions for APlugin {
    fn name(&self) -> &str {
        "APlugin"
    }
    fn deps(&self) -> Vec<&str> {
        vec![]
    }
    fn install(&mut self, engine: &mut Engine) {
        println!("--APlugin--");

        let engine_rc = Rc::new(RefCell::new(engine));

        let engine_move = Rc::clone(&engine_rc);
        let listener = Box::new(move |x| {
            println!("--1--{:?}", x);
            engine_move.borrow_mut().event.emit("list", None);
        });

        engine_rc.borrow_mut().event.on("get-list", listener);
    }
    fn dispose(&mut self, engine: &mut Engine) {}
}

struct BPlugin;
impl PluginOptions for BPlugin {
    fn name(&self) -> &str {
        "BPlugin"
    }
    fn deps(&self) -> Vec<&str> {
        vec!["APlugin"]
    }
    fn install(&mut self, engine: &mut Engine) {
        println!("--BPlugin--");

        engine.event.emit("get-list", Some(1.into()));
        engine.event.on(
            "list",
            Box::new(|x| {
                println!("--2--{:?}", x);
            }),
        );
    }
    fn dispose(&mut self, engine: &mut Engine) {}
}

struct AStrategy;
impl StrategyOptions for AStrategy {
    fn name(&self) -> &str {
        "AStrategy"
    }
    fn condition(&self) -> Vec<&str> {
        vec!["APlugin", "BPlugin"]
    }
    fn exec(&self, engine: &mut Engine) {
        println!("--AStrategy--");
    }
    fn rollback(&mut self, engine: &mut Engine) {}
}

fn main() {
    let mut engine = Engine::new();
    engine.install(APlugin);
    engine.install(BPlugin);
    engine.exec(AStrategy);
}

image

8 posts - 3 participants

Read full topic

🏷️ rust_feed