rust_bus 3.0.6

bus — Lightweight CQRS Library for Rust
Documentation
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, Default)]
pub struct BusMetadata {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub request_id: Option<uuid::Uuid>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub correlation_id: Option<uuid::Uuid>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub causation_id: Option<uuid::Uuid>,
    #[serde(flatten)]
    pub extra: std::collections::HashMap<String, serde_json::Value>,
}

impl BusMetadata {
    pub fn new(
        request_id: Option<uuid::Uuid>,
        correlation_id: Option<uuid::Uuid>,
        causation_id: Option<uuid::Uuid>,
        extra: Option<std::collections::HashMap<String, serde_json::Value>>,
    ) -> Self {
        BusMetadata {
            request_id,
            correlation_id,
            causation_id,
            extra: extra.unwrap_or_default(),
        }
    }

    pub fn add<T: serde::Serialize + serde::de::DeserializeOwned + Clone>(
        &mut self,
        key: &str,
        value: T,
    ) -> Result<(), crate::BusError> {
        let json_value = serde_json::to_value(value).map_err(|e| {
            crate::BusError::MetaData(format!(
                "Failed to serialize metadata value for key '{}': {}",
                key, e
            ))
        })?;

        match key {
            "request_id" | "correlation_id" | "causation_id" => {
                let id: uuid::Uuid = serde_json::from_value(json_value.clone()).map_err(|e| {
                    crate::BusError::MetaData(format!(
                        "Metadata key '{}' expects a valid UUID, but got: {}. Error: {}",
                        key, json_value, e
                    ))
                })?;

                match key {
                    "request_id" => self.request_id = Some(id),
                    "correlation_id" => self.correlation_id = Some(id),
                    "causation_id" => self.causation_id = Some(id),
                    _ => unreachable!(),
                }
            }
            _ => {
                self.extra.insert(key.to_string(), json_value);
            }
        }
        Ok(())
    }

    pub fn get<T: serde::de::DeserializeOwned>(&self, key: &str) -> Option<T> {
        self.extra
            .get(key)
            .and_then(|v| serde_json::from_value(v.clone()).ok())
    }

    pub fn try_get<T: serde::de::DeserializeOwned>(&self, key: &str) -> Result<T, crate::BusError> {
        let value = self.extra.get(key).ok_or_else(|| {
            crate::BusError::MetaData(format!("Metadata key '{}' not found", key))
        })?;
        serde_json::from_value(value.clone()).map_err(|e| {
            crate::BusError::MetaData(format!("Metadata type mismatch for '{}': {}", key, e))
        })
    }
}