moduforge_state/
transaction.rs1use 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 IDS.fetch_add(1, Ordering::SeqCst)
25}
26
27#[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#[derive(Debug, Clone)]
40pub struct Transaction {
41 pub meta: im::HashMap<String, Arc<dyn std::any::Any>>,
43 pub id: u64,
45 pub steps: im::Vector<Arc<dyn Step>>,
47 pub patches: im::Vector<Vec<Patch>>,
49 pub doc: Arc<NodePool>,
51 pub draft: Draft,
53 pub schema: Arc<Schema>,
55}
56unsafe impl Send for Transaction {}
57unsafe impl Sync for Transaction {}
58
59impl Transform for Transaction {
60 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 fn doc_changed(&self) -> bool {
78 !self.steps.is_empty()
79 }
80 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 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 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 pub fn doc(&self) -> Arc<NodePool> {
134 self.doc.clone()
135 }
136 pub fn as_concrete(step: &Arc<dyn Step>) -> ConcreteStep {
138 step.to_concrete()
139 }
140 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 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 pub fn set_time(
162 &mut self,
163 id: u64,
164 ) -> &mut Self {
165 self.id = id;
166 self
167 }
168 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 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}