floxide_core/distributed/
context_store.rs1use crate::context::Context;
2use crate::merge::Merge;
3use async_trait::async_trait;
4use std::collections::HashMap;
5use std::sync::Arc;
6use thiserror::Error;
7use tokio::sync::Mutex;
8#[derive(Debug, Error)]
9pub enum ContextStoreError {
10 #[error("I/O error: {0}")]
11 Io(String),
12 #[error("Other error: {0}")]
13 Other(String),
14}
15
16#[async_trait]
17pub trait ContextStore<C: Context + Merge + Default>: Send + Sync {
18 async fn get(&self, run_id: &str) -> Result<Option<C>, ContextStoreError>;
19 async fn set(&self, run_id: &str, ctx: C) -> Result<(), ContextStoreError>;
20 async fn merge(&self, run_id: &str, ctx: C) -> Result<(), ContextStoreError>;
21}
22
23pub struct InMemoryContextStore<C: Context + Merge + Default> {
25 inner: Arc<Mutex<HashMap<String, C>>>,
26}
27
28impl<C: Context + Merge + Default> Default for InMemoryContextStore<C> {
29 fn default() -> Self {
30 Self {
31 inner: Arc::new(Mutex::new(HashMap::new())),
32 }
33 }
34}
35
36impl<C: Context + Merge + Default> Clone for InMemoryContextStore<C> {
37 fn clone(&self) -> Self {
38 Self {
39 inner: self.inner.clone(),
40 }
41 }
42}
43
44#[async_trait]
45impl<C: Context + Merge + Default> ContextStore<C> for InMemoryContextStore<C> {
46 async fn get(&self, run_id: &str) -> Result<Option<C>, ContextStoreError> {
47 let map = self.inner.lock().await;
48 Ok(map.get(run_id).cloned())
49 }
50 async fn set(&self, run_id: &str, ctx: C) -> Result<(), ContextStoreError> {
51 let mut map = self.inner.lock().await;
52 map.insert(run_id.to_string(), ctx);
53 Ok(())
54 }
55 async fn merge(&self, run_id: &str, ctx: C) -> Result<(), ContextStoreError> {
56 let mut map = self.inner.lock().await;
57 map.entry(run_id.to_string())
58 .and_modify(|existing| existing.merge(ctx.clone()))
59 .or_insert(ctx);
60 Ok(())
61 }
62}