moduforge_state/
plugin.rs

1use async_trait::async_trait;
2use std::sync::Arc;
3
4use crate::error::StateResult;
5use crate::resource::Resource;
6
7use super::state::{State, StateConfig};
8use super::transaction::Transaction;
9
10/// 插件特征
11/// 定义插件的核心行为,包括事务处理和过滤功能
12#[async_trait]
13pub trait PluginTrait: Send + Sync + Debug {
14    /// 追加事务处理
15    /// 允许插件在事务执行前修改或扩展事务内容
16    async fn append_transaction(
17        &self,
18        _: &[Transaction],
19        _: &State,
20        _: &State,
21    ) -> StateResult<Option<Transaction>> {
22        Ok(None)
23    }
24    /// 事务过滤
25    /// 决定是否允许事务执行
26    async fn filter_transaction(
27        &self,
28        _: &Transaction,
29        _: &State,
30    ) -> bool {
31        true
32    }
33}
34/// 状态字段特征
35/// 定义插件状态的管理方式,包括初始化、应用更改和序列化
36#[async_trait]
37pub trait StateField: Send + Sync + Debug {
38    /// 初始化插件状态
39    async fn init(
40        &self,
41        config: &StateConfig,
42        instance: Option<&State>,
43    ) -> Arc<dyn Resource>;
44    /// 应用状态变更
45    /// 根据事务内容更新插件状态
46    async fn apply(
47        &self,
48        tr: &Transaction,
49        value: Arc<dyn Resource>,
50        old_state: &State,
51        new_state: &State,
52    ) -> Arc<dyn Resource>;
53    /// 序列化插件状态
54    fn serialize(
55        &self,
56        _value: Arc<dyn Resource>,
57    ) -> Option<Vec<u8>> {
58        None
59    }
60    /// 反序列化插件状态
61    fn deserialize(
62        &self,
63        _value: &Vec<u8>,
64    ) -> Option<Arc<dyn Resource>> {
65        None
66    }
67}
68/// 插件规范结构体
69/// 定义插件的配置和行为
70#[derive(Clone, Debug)]
71pub struct PluginSpec {
72    pub state_field: Option<Arc<dyn StateField>>,
73    pub key: PluginKey,
74    pub tr: Option<Arc<dyn PluginTrait>>,
75    pub priority: i32,
76}
77
78unsafe impl Send for PluginSpec {}
79unsafe impl Sync for PluginSpec {}
80
81impl PluginSpec {
82    /// 插件状态管理器
83    async fn filter_transaction(
84        &self,
85        tr: &Transaction,
86        state: &State,
87    ) -> bool {
88        match &self.tr {
89            Some(filter) => filter.filter_transaction(tr, state).await,
90            None => false,
91        }
92    }
93    /// 执行事务追加
94    async fn append_transaction<'a>(
95        &self,
96        trs: &'a [Transaction],
97        old_state: &State,
98        new_state: &State,
99    ) -> StateResult<Option<Transaction>> {
100        match &self.tr {
101            Some(transaction) => {
102                let tr = transaction
103                    .append_transaction(trs, old_state, new_state)
104                    .await?;
105                if let Some(mut tr) = tr {
106                    tr.commit();
107                    Ok(Some(tr))
108                } else {
109                    Ok(None)
110                }
111            },
112            None => Ok(None),
113        }
114    }
115}
116/// 插件实例结构体
117/// 表示一个具体的插件实例
118#[derive(Clone, Debug)]
119pub struct Plugin {
120    pub spec: PluginSpec,
121    pub key: String,
122}
123
124unsafe impl Send for Plugin {}
125unsafe impl Sync for Plugin {}
126
127impl Plugin {
128    /// 创建新的插件实例
129    pub fn new(spec: PluginSpec) -> Self {
130        let key = spec.key.0.clone();
131
132        Plugin { spec, key }
133    }
134
135    /// 从全局状态中获取插件状态
136    pub fn get_state(
137        &self,
138        state: &State,
139    ) -> Option<Arc<dyn Resource>> {
140        state.get_field(&self.key)
141    }
142    /// 应用事务过滤逻辑
143    pub async fn apply_filter_transaction(
144        &self,
145        tr: &Transaction,
146        state: &State,
147    ) -> bool {
148        self.spec.filter_transaction(tr, state).await
149    }
150
151    /// 应用事务追加逻辑
152    pub async fn apply_append_transaction(
153        &self,
154        trs: &[Transaction],
155        old_state: &State,
156        new_state: &State,
157    ) -> StateResult<Option<Transaction>> {
158        self.spec.append_transaction(trs, old_state, new_state).await
159    }
160}
161
162/// 插件状态类型
163/// 使用 Arc 包装的任意类型作为插件状态
164//pub type PluginState = Arc<dyn std::any::Any + Send + Sync>;
165use std::fmt::Debug;
166
167/// 插件键类型
168/// 使用两个字符串组成的元组作为插件的唯一标识
169pub type PluginKey = (String, String);