use std::any::Any;
use std::ops::{Deref, DerefMut};
use std::sync::Arc;
use async_trait::async_trait;
use mf_model::mark::Mark;
use mf_model::node_definition::NodeTree;
use mf_model::types::NodeId;
use mf_transform::TransformResult;
use serde_json::Value;
use super::state::State;
use mf_model::node_pool::NodePool;
use mf_transform::attr_step::AttrStep;
use mf_transform::node_step::{AddNodeStep, RemoveNodeStep};
use mf_transform::mark_step::{AddMarkStep, RemoveMarkStep};
use mf_transform::transform::{Transform};
use std::fmt::Debug;
use std::sync::atomic::{AtomicU64, Ordering};
use mf_model::rpds::{HashTrieMapSync};
#[async_trait]
pub trait Command: Send + Sync + Debug {
async fn execute(
&self,
tr: &mut Transaction,
) -> TransformResult<()>;
fn name(&self) -> String;
}
static VERSION: AtomicU64 = AtomicU64::new(1);
pub fn get_tr_id() -> u64 {
VERSION.fetch_add(1, Ordering::SeqCst)
}
#[derive(Clone)]
pub struct Transaction {
pub meta: HashTrieMapSync<String, Arc<dyn Any + Send + Sync>>,
pub id: u64,
transform: Transform,
}
impl Debug for Transaction {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
write!(f, "Transaction {{ id: {}}}", self.id)
}
}
impl Deref for Transaction {
type Target = Transform;
fn deref(&self) -> &Self::Target {
&self.transform
}
}
impl DerefMut for Transaction {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.transform
}
}
impl Transaction {
#[cfg_attr(feature = "dev-tracing", tracing::instrument(skip(state), fields(
crate_name = "state",
state_version = state.version,
doc_size = state.node_pool.size()
)))]
pub fn new(state: &State) -> Self {
let node = state.doc();
let schema = state.schema();
let tr = Transaction {
meta: HashTrieMapSync::new_sync(),
id: get_tr_id(), transform: Transform::new(node, schema),
};
#[cfg(feature = "dev-tracing")]
tracing::debug!(tr_id = %tr.id, "事务创建成功");
tr
}
#[cfg_attr(feature = "dev-tracing", tracing::instrument(skip(self, other), fields(
crate_name = "state",
self_tr_id = %self.id,
other_tr_id = %other.id,
self_steps = self.steps.len(),
other_steps = other.steps.len()
)))]
pub fn merge(
&mut self,
other: &mut Self,
) {
let steps_to_apply: Vec<_> = other.steps.iter().cloned().collect();
if let Err(e) = self.apply_steps_batch(steps_to_apply) {
#[cfg(feature = "dev-tracing")]
tracing::error!(error = %e, "批量应用步骤失败");
eprintln!("批量应用步骤失败: {e}");
} else {
#[cfg(feature = "dev-tracing")]
tracing::debug!(total_steps = self.steps.len(), "事务合并成功");
}
}
pub fn doc(&self) -> Arc<NodePool> {
self.transform.doc()
}
#[cfg_attr(feature = "dev-tracing", tracing::instrument(skip(self, values), fields(
crate_name = "state",
tr_id = %self.id,
node_id = %id,
attr_count = values.len()
)))]
pub fn set_node_attribute(
&mut self,
id: NodeId,
values: HashTrieMapSync<String, Value>,
) -> TransformResult<()> {
self.step(Arc::new(AttrStep::new(id, values)))?;
Ok(())
}
#[cfg_attr(feature = "dev-tracing", tracing::instrument(skip(self, nodes), fields(
crate_name = "state",
tr_id = %self.id,
parent_id = %parent_id,
node_count = nodes.len()
)))]
pub fn add_node(
&mut self,
parent_id: NodeId,
nodes: Vec<NodeTree>,
) -> TransformResult<()> {
self.step(Arc::new(AddNodeStep::new(parent_id, nodes)))?;
Ok(())
}
#[cfg_attr(feature = "dev-tracing", tracing::instrument(skip(self, node_ids), fields(
crate_name = "state",
tr_id = %self.id,
parent_id = %parent_id,
remove_count = node_ids.len()
)))]
pub fn remove_node(
&mut self,
parent_id: NodeId,
node_ids: Vec<NodeId>,
) -> TransformResult<()> {
self.step(Arc::new(RemoveNodeStep::new(parent_id, node_ids)))?;
Ok(())
}
#[cfg_attr(feature = "dev-tracing", tracing::instrument(skip(self, marks), fields(
crate_name = "state",
tr_id = %self.id,
node_id = %id,
mark_count = marks.len()
)))]
pub fn add_mark(
&mut self,
id: NodeId,
marks: Vec<Mark>,
) -> TransformResult<()> {
self.step(Arc::new(AddMarkStep::new(id, marks)))?;
Ok(())
}
#[cfg_attr(feature = "dev-tracing", tracing::instrument(skip(self, mark_types), fields(
crate_name = "state",
tr_id = %self.id,
node_id = %id,
mark_type_count = mark_types.len()
)))]
pub fn remove_mark(
&mut self,
id: NodeId,
mark_types: Vec<String>,
) -> TransformResult<()> {
self.step(Arc::new(RemoveMarkStep::new(id, mark_types)))?;
Ok(())
}
pub fn set_meta<K, T: Send + Sync + 'static>(
&mut self,
key: K,
value: T,
) -> &mut Self
where
K: Into<String>,
{
let key_str = key.into();
self.meta.insert_mut(key_str, Arc::new(value));
self
}
pub fn get_meta<T: Clone + 'static>(
&self,
key: &str,
) -> Option<T> {
let value = self.meta.get(key)?;
value.downcast_ref::<T>().cloned()
}
}