use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use uuid::Uuid;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Event {
pub id: Uuid,
pub event_type: String,
pub payload: Value,
pub timestamp: DateTime<Utc>,
pub source: String,
pub correlation_id: Option<Uuid>,
pub version: String,
}
impl Event {
pub fn new(event_type: String, payload: Value, source: String) -> Self {
Self {
id: Uuid::new_v4(),
event_type,
payload,
timestamp: Utc::now(),
source,
correlation_id: None,
version: "1.0".to_string(),
}
}
pub fn new_with_correlation(
event_type: String,
payload: Value,
source: String,
correlation_id: Uuid,
) -> Self {
Self {
id: Uuid::new_v4(),
event_type,
payload,
timestamp: Utc::now(),
source,
correlation_id: Some(correlation_id),
version: "1.0".to_string(),
}
}
pub fn new_versioned(
event_type: String,
payload: Value,
source: String,
version: String,
) -> Self {
Self {
id: Uuid::new_v4(),
event_type,
payload,
timestamp: Utc::now(),
source,
correlation_id: None,
version,
}
}
pub fn is_type(&self, event_type: &str) -> bool {
self.event_type == event_type
}
pub fn get_payload_field(&self, field: &str) -> Option<&Value> {
self.payload.get(field)
}
pub fn derive_event(&self, new_type: String, new_payload: Value, new_source: String) -> Self {
Self {
id: Uuid::new_v4(),
event_type: new_type,
payload: new_payload,
timestamp: Utc::now(),
source: new_source,
correlation_id: Some(self.correlation_id.unwrap_or(self.id)),
version: self.version.clone(),
}
}
}
impl Default for Event {
fn default() -> Self {
Self {
id: Uuid::new_v4(),
event_type: "unknown".to_string(),
payload: Value::Null,
timestamp: Utc::now(),
source: "system".to_string(),
correlation_id: None,
version: "1.0".to_string(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_event_creation() {
let event = Event::new(
"test_event".to_string(),
json!({"key": "value"}),
"test_source".to_string(),
);
assert_eq!(event.event_type, "test_event");
assert_eq!(event.payload, json!({"key": "value"}));
assert_eq!(event.source, "test_source");
assert_eq!(event.version, "1.0");
assert!(event.correlation_id.is_none());
}
#[test]
fn test_event_with_correlation() {
let correlation_id = Uuid::new_v4();
let event = Event::new_with_correlation(
"correlated_event".to_string(),
json!({"data": "test"}),
"test_source".to_string(),
correlation_id,
);
assert_eq!(event.correlation_id, Some(correlation_id));
}
#[test]
fn test_event_versioned() {
let event = Event::new_versioned(
"versioned_event".to_string(),
json!({"data": "test"}),
"test_source".to_string(),
"2.0".to_string(),
);
assert_eq!(event.version, "2.0");
}
#[test]
fn test_is_type() {
let event = Event::new(
"test_event".to_string(),
json!({}),
"test_source".to_string(),
);
assert!(event.is_type("test_event"));
assert!(!event.is_type("other_event"));
}
#[test]
fn test_get_payload_field() {
let event = Event::new(
"test_event".to_string(),
json!({"key": "value", "number": 42}),
"test_source".to_string(),
);
assert_eq!(event.get_payload_field("key"), Some(&json!("value")));
assert_eq!(event.get_payload_field("number"), Some(&json!(42)));
assert_eq!(event.get_payload_field("missing"), None);
}
#[test]
fn test_derive_event() {
let original = Event::new(
"original_event".to_string(),
json!({"data": "original"}),
"original_source".to_string(),
);
let derived = original.derive_event(
"derived_event".to_string(),
json!({"data": "derived"}),
"derived_source".to_string(),
);
assert_eq!(derived.event_type, "derived_event");
assert_eq!(derived.payload, json!({"data": "derived"}));
assert_eq!(derived.source, "derived_source");
assert_eq!(derived.correlation_id, Some(original.id));
assert_eq!(derived.version, original.version);
}
#[test]
fn test_default_event() {
let event = Event::default();
assert_eq!(event.event_type, "unknown");
assert_eq!(event.payload, Value::Null);
assert_eq!(event.source, "system");
assert_eq!(event.version, "1.0");
}
}