1use async_trait::async_trait;
2use chrono::Utc;
3use std::collections::HashMap;
4use std::sync::Arc;
5use tokio::sync::Mutex;
6use uuid::Uuid;
7
8use crate::error::{FlowError, Result};
9use crate::model::{FlowEvent, FlowEventEnvelope};
10
11use super::FlowEventStore;
12
13#[derive(Debug, Default)]
15pub struct InMemoryEventStore {
16 runs: Arc<Mutex<HashMap<String, Vec<FlowEventEnvelope>>>>,
17}
18
19impl InMemoryEventStore {
20 pub fn new() -> Self {
21 Self::default()
22 }
23}
24
25#[async_trait]
26impl FlowEventStore for InMemoryEventStore {
27 async fn append(&self, run_id: &str, event: FlowEvent) -> Result<FlowEventEnvelope> {
28 let mut runs = self.runs.lock().await;
29 append_in_memory(&mut runs, run_id, event)
30 }
31
32 async fn append_if_sequence(
33 &self,
34 run_id: &str,
35 expected_sequence: u64,
36 event: FlowEvent,
37 ) -> Result<FlowEventEnvelope> {
38 let mut runs = self.runs.lock().await;
39 let actual_sequence = runs
40 .get(run_id)
41 .and_then(|events| events.last())
42 .map_or(0, |event| event.sequence);
43 if actual_sequence != expected_sequence {
44 return Err(FlowError::EventConflict {
45 run_id: run_id.to_string(),
46 expected_sequence,
47 actual_sequence,
48 });
49 }
50 append_in_memory(&mut runs, run_id, event)
51 }
52
53 async fn list(&self, run_id: &str) -> Result<Vec<FlowEventEnvelope>> {
54 let runs = self.runs.lock().await;
55 match runs.get(run_id) {
56 Some(events) => Ok(events.clone()),
57 None => Err(FlowError::RunNotFound(run_id.to_string())),
58 }
59 }
60
61 async fn list_run_ids(&self) -> Result<Vec<String>> {
62 let runs = self.runs.lock().await;
63 let mut ids: Vec<String> = runs.keys().cloned().collect();
64 ids.sort();
65 Ok(ids)
66 }
67}
68
69fn append_in_memory(
70 runs: &mut HashMap<String, Vec<FlowEventEnvelope>>,
71 run_id: &str,
72 event: FlowEvent,
73) -> Result<FlowEventEnvelope> {
74 let events = runs.entry(run_id.to_string()).or_default();
75 let envelope = FlowEventEnvelope {
76 run_id: run_id.to_string(),
77 sequence: events.last().map_or(1, |event| event.sequence + 1),
78 event_id: Uuid::new_v4(),
79 timestamp: Utc::now(),
80 event,
81 };
82 events.push(envelope.clone());
83 Ok(envelope)
84}