store_sqlite/
memory_store.rs1use std::sync::Mutex;
4
5use chrono::Utc;
6use rusqlite::{params, Connection};
7use uuid::Uuid;
8
9use substrate_core::memory_port::{MemoryEntry, MemoryPort};
10
11use crate::error::StoreError;
12use crate::schema;
13
14pub struct SqliteMemoryStore {
16 conn: Mutex<Connection>,
17}
18
19impl SqliteMemoryStore {
20 pub fn open(path: &str) -> Result<Self, StoreError> {
22 let conn = Connection::open(path)?;
23 schema::init(&conn)?;
24 Ok(Self {
25 conn: Mutex::new(conn),
26 })
27 }
28
29 pub fn open_in_memory() -> Result<Self, StoreError> {
31 let conn = Connection::open_in_memory()?;
32 schema::init(&conn)?;
33 Ok(Self {
34 conn: Mutex::new(conn),
35 })
36 }
37}
38
39impl MemoryPort for SqliteMemoryStore {
40 type Error = StoreError;
41
42 fn append(&self, key: &str, content: &str) -> Result<Uuid, Self::Error> {
43 let id = Uuid::new_v4();
44 let created_at = Utc::now().timestamp();
45 let conn = self.conn.lock().unwrap();
46 conn.execute(
47 "INSERT INTO memory (id, mem_key, content, created_at) VALUES (?1, ?2, ?3, ?4)",
48 params![id.to_string(), key, content, created_at],
49 )?;
50 Ok(id)
51 }
52
53 fn get(&self, key: &str) -> Result<Option<String>, Self::Error> {
54 let conn = self.conn.lock().unwrap();
55 let mut stmt = conn.prepare(
56 "SELECT content FROM memory WHERE mem_key = ?1 ORDER BY created_at DESC LIMIT 1",
57 )?;
58 let mut rows = stmt.query(params![key])?;
59 if let Some(row) = rows.next()? {
60 Ok(Some(row.get(0)?))
61 } else {
62 Ok(None)
63 }
64 }
65
66 fn recent(&self, limit: usize) -> Result<Vec<MemoryEntry>, Self::Error> {
67 self.history_limited(limit)
68 }
69
70 fn history(&self) -> Result<Vec<MemoryEntry>, Self::Error> {
71 self.history_limited(usize::MAX)
72 }
73}
74
75impl SqliteMemoryStore {
76 fn history_limited(&self, limit: usize) -> Result<Vec<MemoryEntry>, StoreError> {
77 let conn = self.conn.lock().unwrap();
78 let mut stmt = conn.prepare(
79 "SELECT id, mem_key, content, created_at FROM memory ORDER BY created_at DESC LIMIT ?1",
80 )?;
81 let rows = stmt.query_map(params![limit as i64], |row| {
82 Ok(MemoryEntry {
83 id: Uuid::parse_str(&row.get::<_, String>(0)?).unwrap_or_else(|_| Uuid::nil()),
84 key: row.get(1)?,
85 content: row.get(2)?,
86 created_at: row.get(3)?,
87 })
88 })?;
89 rows.collect::<Result<Vec<_>, _>>()
90 .map_err(StoreError::from)
91 }
92}