moduforge_state/
transaction.rs

1use std::sync::atomic::{AtomicU64, Ordering};
2use std::sync::Arc;
3
4use async_trait::async_trait;
5use serde_json::Value;
6use tracing::{info, warn, error};
7
8use super::state::State;
9use moduforge_transform::draft::Draft;
10use moduforge_transform::patch::Patch;
11use moduforge_model::node::Node;
12use moduforge_model::node_pool::{NodePool};
13use moduforge_model::schema::Schema;
14use moduforge_transform::attr_step::AttrStep;
15use moduforge_transform::node_step::AddNodeStep;
16use moduforge_transform::step::{Step, StepResult};
17use moduforge_transform::transform::{Transform, TransformError};
18use moduforge_transform::{ConcreteStep, PatchStep};
19use std::fmt::Debug;
20
21static IDS: AtomicU64 = AtomicU64::new(1);
22pub fn get_transaction_id() -> u64 {
23    //生成 全局自增的版本号,用于兼容性
24    IDS.fetch_add(1, Ordering::SeqCst)
25}
26
27/// 定义可执行的命令接口
28/// 要求实现 Send + Sync 以支持并发操作,并实现 Debug 以支持调试
29#[async_trait]
30pub trait Command: Send + Sync + Debug {
31    async fn execute(
32        &self,
33        tr: &mut Transaction,
34    ) -> Result<(), TransformError>;
35    fn name(&self) -> String;
36}
37
38/// 事务结构体,用于管理文档的修改操作
39#[derive(Debug, Clone)]
40pub struct Transaction {
41    /// 存储元数据的哈希表,支持任意类型数据
42    pub meta: im::HashMap<String, Arc<dyn std::any::Any>>,
43    /// 事务的时间戳
44    pub id: u64,
45    /// 存储所有操作步骤
46    pub steps: im::Vector<Arc<dyn Step>>,
47    /// 存储每个步骤对应的补丁列表
48    pub patches: im::Vector<Vec<Patch>>,
49    /// 当前文档状态
50    pub doc: Arc<NodePool>,
51    /// 文档的草稿状态,用于临时修改
52    pub draft: Draft,
53    /// 文档的模式定义
54    pub schema: Arc<Schema>,
55}
56unsafe impl Send for Transaction {}
57unsafe impl Sync for Transaction {}
58
59impl Transform for Transaction {
60    /// 执行一个修改步骤
61    /// step: 要执行的步骤
62    /// 返回: Result,表示执行成功或失败
63    fn step(
64        &mut self,
65        step: Arc<dyn Step>,
66    ) -> Result<(), TransformError> {
67        let result = step.apply(&mut self.draft, self.schema.clone())?;
68        match result.failed {
69            Some(message) => Err(TransformError::new(message)),
70            None => {
71                self.add_step(step, result);
72                Ok(())
73            },
74        }
75    }
76    /// 检查文档是否被修改
77    fn doc_changed(&self) -> bool {
78        !self.steps.is_empty()
79    }
80    /// 添加一个步骤及其结果到事务中
81    fn add_step(
82        &mut self,
83        step: Arc<dyn Step>,
84        result: StepResult,
85    ) {
86        self.steps.push_back(step);
87        self.patches.push_back(result.patches);
88        self.doc = result.doc.unwrap();
89    }
90}
91impl Transaction {
92    /// 执行一个事务操作
93    /// call_back: 要执行的命令
94    pub async fn transaction(
95        &mut self,
96        call_back: Arc<dyn Command>,
97    ) {
98        info!("开始执行事务: {}", call_back.name());
99        self.draft.begin = true;
100        let result = call_back.execute(self).await;
101        self.draft.begin = false;
102        match result {
103            Ok(_) => {
104                info!("事务执行成功,正在提交更改");
105                let result = self.draft.commit();
106                self.add_step(
107                    Arc::new(PatchStep { patches: result.patches.clone() }),
108                    result,
109                );
110            },
111            Err(e) => {
112                error!("事务执行失败: {}", e);
113                warn!("事务回滚");
114            },
115        }
116    }
117    /// 创建新的事务实例
118    /// state: 当前状态对象
119    /// 返回: Transaction 实例
120    pub fn new(state: &State) -> Self {
121        let node = state.doc();
122        Transaction {
123            meta: im::HashMap::new(),
124            id: get_transaction_id(),
125            steps: im::Vector::new(),
126            doc: node,
127            schema: state.schema(),
128            draft: Draft::new(state.doc()),
129            patches: im::Vector::new(),
130        }
131    }
132    /// 获取当前文档状态
133    pub fn doc(&self) -> Arc<NodePool> {
134        self.doc.clone()
135    }
136    /// 将步骤转换为具体步骤
137    pub fn as_concrete(step: &Arc<dyn Step>) -> ConcreteStep {
138        step.to_concrete()
139    }
140    /// 设置节点属性
141    /// id: 节点ID
142    /// values: 属性键值对
143    pub fn set_node_attribute(
144        &mut self,
145        id: String,
146        values: im::HashMap<String, Value>,
147    ) {
148        let _ = self.step(Arc::new(AttrStep::new(id, values)));
149    }
150    /// 添加新节点
151    /// parent_id: 父节点ID
152    /// node: 要添加的节点
153    pub fn add_node(
154        &mut self,
155        parent_id: String,
156        nodes: Vec<Node>,
157    ) {
158        let _ = self.step(Arc::new(AddNodeStep::new(parent_id, nodes)));
159    }
160    /// 设置事务时间戳
161    pub fn set_time(
162        &mut self,
163        id: u64,
164    ) -> &mut Self {
165        self.id = id;
166        self
167    }
168    /// 设置元数据
169    /// key: 键
170    /// value: 值(支持任意类型)
171    pub fn set_meta<K, T: std::any::Any>(
172        &mut self,
173        key: K,
174        value: T,
175    ) -> &mut Self
176    where
177        K: Into<String>,
178    {
179        let key_str = key.into();
180        self.meta.insert(key_str, Arc::new(value));
181        self
182    }
183    /// 获取元数据
184    /// key: 键
185    /// 返回: Option<&T>,如果存在且类型匹配则返回Some,否则返回None
186    pub fn get_meta<T: 'static, K>(
187        &self,
188        key: K,
189    ) -> Option<&T>
190    where
191        K: Into<String>,
192    {
193        let key_str = key.into();
194        self.meta.get(&key_str)?.downcast_ref::<T>()
195    }
196}