1use std::sync::Arc;
2
3use teaql_core::{Record, Value};
4
5use crate::{RuntimeError, UserContext};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum EntityEventKind {
9 Created,
10 Updated,
11 Deleted,
12 Recovered,
13}
14
15#[derive(Debug, Clone, PartialEq)]
16pub struct EntityEvent {
17 pub kind: EntityEventKind,
18 pub entity: String,
19 pub values: Record,
20 pub updated_fields: Vec<String>,
21}
22
23impl EntityEvent {
24 pub fn created(entity: impl Into<String>, values: Record) -> Self {
25 Self {
26 kind: EntityEventKind::Created,
27 entity: entity.into(),
28 values,
29 updated_fields: Vec::new(),
30 }
31 }
32
33 pub fn updated(entity: impl Into<String>, values: Record) -> Self {
34 let updated_fields = values.keys().cloned().collect();
35 Self {
36 kind: EntityEventKind::Updated,
37 entity: entity.into(),
38 values,
39 updated_fields,
40 }
41 }
42
43 pub fn deleted(entity: impl Into<String>, id: Value, expected_version: Option<i64>) -> Self {
44 let mut values = Record::from([("id".to_owned(), id)]);
45 if let Some(version) = expected_version {
46 values.insert("version".to_owned(), Value::I64(version));
47 }
48 Self {
49 kind: EntityEventKind::Deleted,
50 entity: entity.into(),
51 values,
52 updated_fields: Vec::new(),
53 }
54 }
55
56 pub fn recovered(entity: impl Into<String>, id: Value, expected_version: i64) -> Self {
57 Self {
58 kind: EntityEventKind::Recovered,
59 entity: entity.into(),
60 values: Record::from([
61 ("id".to_owned(), id),
62 ("version".to_owned(), Value::I64(expected_version)),
63 ]),
64 updated_fields: Vec::new(),
65 }
66 }
67}
68
69pub trait EntityEventSink: Send + Sync {
70 fn on_event(&self, ctx: &UserContext, event: &EntityEvent) -> Result<(), RuntimeError>;
71}
72
73#[derive(Default, Clone)]
74pub struct InMemoryEntityEventSink {
75 sinks: Vec<Arc<dyn EntityEventSink>>,
76}
77
78impl InMemoryEntityEventSink {
79 pub fn new() -> Self {
80 Self::default()
81 }
82
83 pub fn register(&mut self, sink: impl EntityEventSink + 'static) {
84 self.sinks.push(Arc::new(sink));
85 }
86
87 pub fn with_sink(mut self, sink: impl EntityEventSink + 'static) -> Self {
88 self.register(sink);
89 self
90 }
91}
92
93impl EntityEventSink for InMemoryEntityEventSink {
94 fn on_event(&self, ctx: &UserContext, event: &EntityEvent) -> Result<(), RuntimeError> {
95 for sink in &self.sinks {
96 sink.on_event(ctx, event)?;
97 }
98 Ok(())
99 }
100}