moduforge_state/
transaction.rs1use std::ops::{Deref, DerefMut};
2use std::sync::atomic::{AtomicU64, Ordering};
3use std::sync::Arc;
4
5use async_trait::async_trait;
6use serde_json::Value;
7use tracing::{info, warn, error};
8
9use super::state::State;
10use moduforge_transform::draft::Draft;
11use moduforge_model::node::Node;
12use moduforge_model::node_pool::{NodePool};
13use moduforge_transform::attr_step::AttrStep;
14use moduforge_transform::node_step::AddNodeStep;
15use moduforge_transform::step::{Step, StepResult};
16use moduforge_transform::transform::{Transform, TransformError};
17use moduforge_transform::{ConcreteStep, PatchStep};
18use std::fmt::Debug;
19
20static IDS: AtomicU64 = AtomicU64::new(1);
21pub fn get_transaction_id() -> u64 {
22 IDS.fetch_add(1, Ordering::SeqCst)
24}
25
26#[async_trait]
29pub trait Command: Send + Sync + Debug {
30 async fn execute(
31 &self,
32 tr: &mut Transaction,
33 ) -> Result<(), TransformError>;
34 fn name(&self) -> String;
35}
36
37#[derive(Debug, Clone)]
39pub struct Transaction {
40 pub meta: im::HashMap<String, Arc<dyn std::any::Any>>,
42 pub id: u64,
44 transform:Transform
45}
46unsafe impl Send for Transaction {}
47unsafe impl Sync for Transaction {}
48impl Deref for Transaction {
49 type Target = Transform;
50
51 fn deref(&self) -> &Self::Target {
52 &self.transform
53 }
54}
55
56impl DerefMut for Transaction {
57 fn deref_mut(&mut self) -> &mut Self::Target {
58 &mut self.transform
59 }
60}
61
62impl Transaction {
63 pub async fn transaction(
66 &mut self,
67 call_back: Arc<dyn Command>,
68 ) {
69 info!("开始执行事务: {}", call_back.name());
70 self.draft.begin = true;
71 let result = call_back.execute(self).await;
72 self.draft.begin = false;
73 match result {
74 Ok(_) => {
75 info!("事务执行成功,正在提交更改");
76 let result = self.draft.commit();
77 self.add_step(
78 Arc::new(PatchStep { patches: result.patches.clone() }),
79 result,
80 );
81 },
82 Err(e) => {
83 error!("事务执行失败: {}", e);
84 warn!("事务回滚");
85 },
86 }
87 }
88 pub fn new(state: &State) -> Self {
92 let node = state.doc();
93 let schema = state.schema();
94 Transaction {
95 meta: im::HashMap::new(),
96 id: get_transaction_id(),
97 transform: Transform {
98 doc: node.clone(),
99 draft: Draft::new(node),
100 steps: im::Vector::new(),
101 patches: im::Vector::new(),
102 schema,
103 },
104 }
105 }
106 pub fn doc(&self) -> Arc<NodePool> {
108 self.doc.clone()
109 }
110 pub fn as_concrete(step: &Arc<dyn Step>) -> ConcreteStep {
112 step.to_concrete()
113 }
114 pub fn set_node_attribute(
118 &mut self,
119 id: String,
120 values: im::HashMap<String, Value>,
121 ) {
122 let _ = self.step(Arc::new(AttrStep::new(id, values)));
123 }
124 pub fn add_node(
128 &mut self,
129 parent_id: String,
130 nodes: Vec<Node>,
131 ) {
132 let _ = self.step(Arc::new(AddNodeStep::new(parent_id, nodes)));
133 }
134 pub fn set_time(
136 &mut self,
137 id: u64,
138 ) -> &mut Self {
139 self.id = id;
140 self
141 }
142 pub fn set_meta<K, T: std::any::Any>(
146 &mut self,
147 key: K,
148 value: T,
149 ) -> &mut Self
150 where
151 K: Into<String>,
152 {
153 let key_str = key.into();
154 self.meta.insert(key_str, Arc::new(value));
155 self
156 }
157 pub fn get_meta<T: 'static, K>(
161 &self,
162 key: K,
163 ) -> Option<&T>
164 where
165 K: Into<String>,
166 {
167 let key_str = key.into();
168 self.meta.get(&key_str)?.downcast_ref::<T>()
169 }
170}