moduforge_core/state/
transaction.rs

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