1use async_trait::async_trait;
2use forja_core::error::Result;
3use forja_core::traits::MemoryStore;
4use forja_core::types::MemoryEntry;
5use std::path::Path;
6use std::fmt::Display;
7
8pub mod storage;
9
10use storage::Storage;
11
12pub struct MarkdownMemoryStore {
13 storage: Storage,
14}
15
16impl MarkdownMemoryStore {
17 pub async fn new(memory_path: impl AsRef<Path>) -> Result<Self> {
18 let storage = Storage::init(memory_path).await?;
19 Ok(Self { storage })
20 }
21
22 pub async fn flush_and_summarize<F, O>(&self, summarizer: F) -> Result<()>
23 where
24 F: Fn(String) -> O,
25 O: SummarizeOutput,
26 {
27 self.storage
28 .flush_and_summarize(|block| summarizer(block).into_summary_result())
29 .await
30 }
31}
32
33pub trait SummarizeOutput {
34 fn into_summary_result(self) -> std::result::Result<String, String>;
35}
36
37impl SummarizeOutput for String {
38 fn into_summary_result(self) -> std::result::Result<String, String> {
39 Ok(self)
40 }
41}
42
43impl<E> SummarizeOutput for std::result::Result<String, E>
44where
45 E: Display,
46{
47 fn into_summary_result(self) -> std::result::Result<String, String> {
48 self.map_err(|error| error.to_string())
49 }
50}
51
52#[async_trait]
53impl MemoryStore for MarkdownMemoryStore {
54 async fn save(&self, entry: &MemoryEntry) -> Result<()> {
55 self.storage.append_entry(entry).await
56 }
57
58 async fn load_all(&self) -> Result<String> {
59 self.storage.read_all().await
60 }
61
62 async fn flush(&self) -> Result<()> {
63 Ok(())
64 }
65}