1use async_trait::async_trait;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6use uuid::Uuid;
7
8use khive_types::{EventKind, EventOutcome, SubstrateKind};
9
10use crate::types::{BatchWriteSummary, Page, PageRequest, StorageResult};
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct Event {
16 pub id: Uuid,
17 pub namespace: String,
18 pub verb: String,
19 pub substrate: SubstrateKind,
20 pub actor: String,
21 pub kind: EventKind,
22 pub outcome: EventOutcome,
23 pub payload: Value,
24 pub payload_schema_version: u32,
25 pub profile_state_version: Option<u64>,
26 pub duration_us: i64,
27 pub target_id: Option<Uuid>,
28 pub session_id: Option<Uuid>,
29 pub aggregate_kind: Option<String>,
30 pub aggregate_id: Option<Uuid>,
31 pub created_at: i64,
32}
33
34impl Event {
35 pub fn new(
37 namespace: impl Into<String>,
38 verb: impl Into<String>,
39 kind: EventKind,
40 substrate: SubstrateKind,
41 actor: impl Into<String>,
42 ) -> Self {
43 Self {
44 id: Uuid::new_v4(),
45 namespace: namespace.into(),
46 verb: verb.into(),
47 substrate,
48 actor: actor.into(),
49 kind,
50 outcome: EventOutcome::Success,
51 payload: Value::Object(Default::default()),
52 payload_schema_version: 1,
53 profile_state_version: None,
54 duration_us: 0,
55 target_id: None,
56 session_id: None,
57 aggregate_kind: None,
58 aggregate_id: None,
59 created_at: chrono::Utc::now().timestamp_micros(),
60 }
61 }
62
63 pub fn with_outcome(mut self, o: EventOutcome) -> Self {
65 self.outcome = o;
66 self
67 }
68
69 pub fn with_payload(mut self, payload: Value) -> Self {
71 self.payload = payload;
72 self
73 }
74
75 pub fn with_payload_schema_version(mut self, version: u32) -> Self {
77 self.payload_schema_version = version;
78 self
79 }
80
81 pub fn with_profile_state_version(mut self, version: u64) -> Self {
83 self.profile_state_version = Some(version);
84 self
85 }
86
87 pub fn with_duration_us(mut self, us: i64) -> Self {
89 self.duration_us = us;
90 self
91 }
92
93 pub fn with_target(mut self, id: Uuid) -> Self {
95 self.target_id = Some(id);
96 self
97 }
98
99 pub fn with_session_id(mut self, id: Uuid) -> Self {
101 self.session_id = Some(id);
102 self
103 }
104
105 pub fn with_aggregate(mut self, kind: impl Into<String>, id: Uuid) -> Self {
107 self.aggregate_kind = Some(kind.into());
108 self.aggregate_id = Some(id);
109 self
110 }
111}
112
113#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
115#[serde(rename_all = "snake_case")]
116pub enum ReferentKind {
117 Entity,
118 Note,
119}
120
121impl ReferentKind {
122 pub const fn name(self) -> &'static str {
124 match self {
125 Self::Entity => "entity",
126 Self::Note => "note",
127 }
128 }
129}
130
131#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
133#[serde(rename_all = "snake_case")]
134pub enum ObservationRole {
135 Candidate,
136 Selected,
137 Target,
138 Signal,
139}
140
141impl ObservationRole {
142 pub const fn name(self) -> &'static str {
144 match self {
145 Self::Candidate => "candidate",
146 Self::Selected => "selected",
147 Self::Target => "target",
148 Self::Signal => "signal",
149 }
150 }
151}
152
153#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
155pub struct EventObservation {
156 pub event_id: Uuid,
157 pub entity_id: Uuid,
158 pub referent_kind: ReferentKind,
159 pub role: ObservationRole,
160 pub position: u32,
161}
162
163#[derive(Debug, Clone, Serialize, Deserialize)]
165pub struct EventView {
166 pub event: Event,
167 pub observations: Vec<EventObservation>,
168}
169
170#[derive(Clone, Debug, Default, Serialize, Deserialize)]
172pub struct EventFilter {
173 pub ids: Vec<Uuid>,
174 pub kinds: Vec<EventKind>,
175 pub verbs: Vec<String>,
176 pub substrates: Vec<SubstrateKind>,
177 pub actors: Vec<String>,
178 pub after: Option<i64>,
179 pub before: Option<i64>,
180 pub session_id: Option<Uuid>,
181 pub observed: Vec<Uuid>,
182 pub selected: Vec<Uuid>,
183 pub payload_proposal_id: Option<Uuid>,
184}
185
186#[async_trait]
188pub trait EventStore: Send + Sync + 'static {
189 async fn append_event(&self, event: Event) -> StorageResult<()>;
191 async fn append_events(&self, events: Vec<Event>) -> StorageResult<BatchWriteSummary>;
193 async fn get_event(&self, id: Uuid) -> StorageResult<Option<Event>>;
195 async fn query_events(
197 &self,
198 filter: EventFilter,
199 page: PageRequest,
200 ) -> StorageResult<Page<Event>>;
201 async fn count_events(&self, filter: EventFilter) -> StorageResult<u64>;
203}