Skip to main content

weavatrix_memory/
event.rs

1use crate::{
2    error::{MemoryError, Result},
3    id::{AgentId, EventId, SessionId, StreamId},
4    time::Timestamp,
5};
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
9pub struct NewEvent<E> {
10    pub id: EventId,
11    pub event_type: String,
12    pub occurred_at: Timestamp,
13    pub recorded_at: Timestamp,
14    pub agent_id: AgentId,
15    pub session_id: SessionId,
16    #[serde(skip_serializing_if = "Option::is_none")]
17    pub correlation_id: Option<EventId>,
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub causation_id: Option<EventId>,
20    pub payload: E,
21}
22
23impl<E> NewEvent<E> {
24    /// Creates an uncommitted event with caller-controlled time and identity.
25    ///
26    /// # Errors
27    ///
28    /// Rejects an empty event type or surrounding whitespace.
29    pub fn new(
30        id: EventId,
31        event_type: impl Into<String>,
32        occurred_at: Timestamp,
33        recorded_at: Timestamp,
34        agent_id: AgentId,
35        session_id: SessionId,
36        payload: E,
37    ) -> Result<Self> {
38        let event_type = event_type.into();
39        if event_type.is_empty() || event_type.trim() != event_type {
40            return Err(MemoryError::InvalidValue {
41                field: "event_type",
42                reason: "must be non-empty without surrounding whitespace",
43            });
44        }
45        if occurred_at > recorded_at {
46            return Err(MemoryError::InvalidValue {
47                field: "occurred_at",
48                reason: "must not be later than recorded_at",
49            });
50        }
51        Ok(Self {
52            id,
53            event_type,
54            occurred_at,
55            recorded_at,
56            agent_id,
57            session_id,
58            correlation_id: None,
59            causation_id: None,
60            payload,
61        })
62    }
63
64    #[must_use]
65    pub fn correlated_with(mut self, id: EventId) -> Self {
66        self.correlation_id = Some(id);
67        self
68    }
69
70    #[must_use]
71    pub fn caused_by(mut self, id: EventId) -> Self {
72        self.causation_id = Some(id);
73        self
74    }
75}
76
77#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
78pub struct EventMetadata {
79    pub id: EventId,
80    pub stream_id: StreamId,
81    pub stream_version: u64,
82    pub global_position: u64,
83    pub event_type: String,
84    pub occurred_at: Timestamp,
85    pub recorded_at: Timestamp,
86    pub agent_id: AgentId,
87    pub session_id: SessionId,
88    #[serde(skip_serializing_if = "Option::is_none")]
89    pub correlation_id: Option<EventId>,
90    #[serde(skip_serializing_if = "Option::is_none")]
91    pub causation_id: Option<EventId>,
92}
93
94#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
95pub struct StoredEvent<E> {
96    pub metadata: EventMetadata,
97    pub payload: E,
98}