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(
36 namespace: impl Into<String>,
37 verb: impl Into<String>,
38 kind: EventKind,
39 substrate: SubstrateKind,
40 actor: impl Into<String>,
41 ) -> Self {
42 Self {
43 id: Uuid::new_v4(),
44 namespace: namespace.into(),
45 verb: verb.into(),
46 substrate,
47 actor: actor.into(),
48 kind,
49 outcome: EventOutcome::Success,
50 payload: Value::Object(Default::default()),
51 payload_schema_version: 1,
52 profile_state_version: None,
53 duration_us: 0,
54 target_id: None,
55 session_id: None,
56 aggregate_kind: None,
57 aggregate_id: None,
58 created_at: chrono::Utc::now().timestamp_micros(),
59 }
60 }
61
62 pub fn with_outcome(mut self, o: EventOutcome) -> Self {
63 self.outcome = o;
64 self
65 }
66
67 pub fn with_payload(mut self, payload: Value) -> Self {
68 self.payload = payload;
69 self
70 }
71
72 pub fn with_payload_schema_version(mut self, version: u32) -> Self {
73 self.payload_schema_version = version;
74 self
75 }
76
77 pub fn with_profile_state_version(mut self, version: u64) -> Self {
78 self.profile_state_version = Some(version);
79 self
80 }
81
82 pub fn with_duration_us(mut self, us: i64) -> Self {
83 self.duration_us = us;
84 self
85 }
86
87 pub fn with_target(mut self, id: Uuid) -> Self {
88 self.target_id = Some(id);
89 self
90 }
91
92 pub fn with_session_id(mut self, id: Uuid) -> Self {
93 self.session_id = Some(id);
94 self
95 }
96
97 pub fn with_aggregate(mut self, kind: impl Into<String>, id: Uuid) -> Self {
98 self.aggregate_kind = Some(kind.into());
99 self.aggregate_id = Some(id);
100 self
101 }
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
105#[serde(rename_all = "snake_case")]
106pub enum ReferentKind {
107 Entity,
108 Note,
109}
110
111impl ReferentKind {
112 pub const fn name(self) -> &'static str {
113 match self {
114 Self::Entity => "entity",
115 Self::Note => "note",
116 }
117 }
118}
119
120#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
121#[serde(rename_all = "snake_case")]
122pub enum ObservationRole {
123 Candidate,
124 Selected,
125 Target,
126 Signal,
127}
128
129impl ObservationRole {
130 pub const fn name(self) -> &'static str {
131 match self {
132 Self::Candidate => "candidate",
133 Self::Selected => "selected",
134 Self::Target => "target",
135 Self::Signal => "signal",
136 }
137 }
138}
139
140#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
141pub struct EventObservation {
142 pub event_id: Uuid,
143 pub entity_id: Uuid,
144 pub referent_kind: ReferentKind,
145 pub role: ObservationRole,
146 pub position: u32,
147}
148
149#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct EventView {
151 pub event: Event,
152 pub observations: Vec<EventObservation>,
153}
154
155#[derive(Clone, Debug, Default, Serialize, Deserialize)]
157pub struct EventFilter {
158 pub ids: Vec<Uuid>,
159 pub kinds: Vec<EventKind>,
160 pub verbs: Vec<String>,
161 pub substrates: Vec<SubstrateKind>,
162 pub actors: Vec<String>,
163 pub after: Option<i64>,
164 pub before: Option<i64>,
165 pub session_id: Option<Uuid>,
166 pub observed: Vec<Uuid>,
167 pub selected: Vec<Uuid>,
168 pub payload_proposal_id: Option<Uuid>,
169}
170
171#[async_trait]
172pub trait EventStore: Send + Sync + 'static {
173 async fn append_event(&self, event: Event) -> StorageResult<()>;
174 async fn append_events(&self, events: Vec<Event>) -> StorageResult<BatchWriteSummary>;
175 async fn get_event(&self, id: Uuid) -> StorageResult<Option<Event>>;
176 async fn query_events(
177 &self,
178 filter: EventFilter,
179 page: PageRequest,
180 ) -> StorageResult<Page<Event>>;
181 async fn count_events(&self, filter: EventFilter) -> StorageResult<u64>;
182}