disyn_memory/
in_memory.rs1use async_trait::async_trait;
2use std::sync::Mutex;
3
4use disyn_core::Result;
5use disyn_core::ports::MemoryStore;
6use disyn_core::types::{ExecutionReport, Facts, MemoryContext};
7
8pub struct InMemoryStore {
9 episodes: Mutex<Vec<ExecutionReport>>,
10}
11
12impl InMemoryStore {
13 pub fn new() -> Self {
14 Self {
15 episodes: Mutex::new(Vec::new()),
16 }
17 }
18}
19
20impl Default for InMemoryStore {
21 fn default() -> Self {
22 Self::new()
23 }
24}
25
26#[async_trait]
27impl MemoryStore for InMemoryStore {
28 async fn retrieve(&self, _facts: &Facts) -> Result<MemoryContext> {
29 Ok(MemoryContext {
30 relevant_episodes: vec![],
31 summary: None,
32 weighted_passages: vec![],
33 })
34 }
35
36 async fn persist(&self, report: &ExecutionReport) -> Result<()> {
37 self.episodes
38 .lock()
39 .map_err(|e| disyn_core::Error::Memory(e.to_string()))?
40 .push(report.clone());
41 Ok(())
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48
49 #[tokio::test]
50 async fn retrieve_returns_empty_context_initially() {
51 let store = InMemoryStore::new();
52 let facts = Facts {
53 entities: vec!["test".into()],
54 relations: vec![],
55 confidence: 1.0,
56 };
57 let ctx = store.retrieve(&facts).await.unwrap();
58 assert!(ctx.relevant_episodes.is_empty());
59 assert!(ctx.summary.is_none());
60 }
61}