use crate::engine::error::ErrorInfo;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
use std::sync::Arc;
use uuid::Uuid;
#[derive(Debug, Clone)]
pub struct Message {
pub id: String,
pub payload: Arc<Value>,
pub context: Value,
pub audit_trail: Vec<AuditTrail>,
pub errors: Vec<ErrorInfo>,
context_arc_cache: Option<Arc<Value>>,
}
impl Serialize for Message {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeStruct;
let mut state = serializer.serialize_struct("Message", 5)?;
state.serialize_field("id", &self.id)?;
state.serialize_field("payload", &self.payload)?;
state.serialize_field("context", &self.context)?;
state.serialize_field("audit_trail", &self.audit_trail)?;
state.serialize_field("errors", &self.errors)?;
state.end()
}
}
impl<'de> Deserialize<'de> for Message {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
#[derive(Deserialize)]
struct MessageData {
id: String,
payload: Arc<Value>,
context: Value,
audit_trail: Vec<AuditTrail>,
errors: Vec<ErrorInfo>,
}
let data = MessageData::deserialize(deserializer)?;
Ok(Message {
id: data.id,
payload: data.payload,
context: data.context,
audit_trail: data.audit_trail,
errors: data.errors,
context_arc_cache: None,
})
}
}
impl Message {
pub fn new(payload: Arc<Value>) -> Self {
Self {
id: Uuid::new_v4().to_string(),
payload,
context: json!({
"data": {},
"metadata": {},
"temp_data": {}
}),
audit_trail: vec![],
errors: vec![],
context_arc_cache: None,
}
}
pub fn get_context_arc(&mut self) -> Arc<Value> {
if let Some(ref arc) = self.context_arc_cache {
Arc::clone(arc)
} else {
let arc = Arc::new(self.context.clone());
self.context_arc_cache = Some(Arc::clone(&arc));
arc
}
}
pub fn invalidate_context_cache(&mut self) {
self.context_arc_cache = None;
}
pub fn from_value(payload: &Value) -> Self {
Self::new(Arc::new(payload.clone()))
}
pub fn from_arc(payload: Arc<Value>) -> Self {
Self::new(payload)
}
pub fn add_error(&mut self, error: ErrorInfo) {
self.errors.push(error);
}
pub fn has_errors(&self) -> bool {
!self.errors.is_empty()
}
pub fn data(&self) -> &Value {
&self.context["data"]
}
pub fn data_mut(&mut self) -> &mut Value {
&mut self.context["data"]
}
pub fn metadata(&self) -> &Value {
&self.context["metadata"]
}
pub fn metadata_mut(&mut self) -> &mut Value {
&mut self.context["metadata"]
}
pub fn temp_data(&self) -> &Value {
&self.context["temp_data"]
}
pub fn temp_data_mut(&mut self) -> &mut Value {
&mut self.context["temp_data"]
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct AuditTrail {
pub workflow_id: Arc<str>,
pub task_id: Arc<str>,
pub timestamp: DateTime<Utc>,
pub changes: Vec<Change>,
pub status: usize,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Change {
pub path: Arc<str>,
pub old_value: Arc<Value>,
pub new_value: Arc<Value>,
}