do_memory_storage_turso/storage/
heuristics.rs1use crate::TursoStorage;
4use do_memory_core::{Error, Heuristic, Result};
5use libsql::Row;
6use tracing::{debug, info};
7use uuid::Uuid;
8
9impl TursoStorage {
10 pub async fn store_heuristic(&self, heuristic: &Heuristic) -> Result<()> {
12 debug!("Storing heuristic: {}", heuristic.heuristic_id);
13 let (conn, _conn_id) = self.get_connection_with_id().await?;
14
15 const SQL: &str = r#"
16 INSERT OR REPLACE INTO heuristics (
17 heuristic_id, condition_text, action_text, confidence, evidence, created_at, updated_at
18 ) VALUES (?, ?, ?, ?, ?, ?, ?)
19 "#;
20
21 let evidence_json =
22 serde_json::to_string(&heuristic.evidence).map_err(Error::Serialization)?;
23
24 let stmt = self
26 .prepared_cache
27 .get_or_prepare(&conn, SQL)
28 .await
29 .map_err(|e| Error::Storage(format!("Failed to prepare statement: {}", e)))?;
30
31 stmt.execute(libsql::params![
32 heuristic.heuristic_id.to_string(),
33 heuristic.condition.clone(),
34 heuristic.action.clone(),
35 heuristic.confidence,
36 evidence_json,
37 heuristic.created_at.timestamp(),
38 heuristic.updated_at.timestamp(),
39 ])
40 .await
41 .map_err(|e| Error::Storage(format!("Failed to store heuristic: {}", e)))?;
42
43 info!("Successfully stored heuristic: {}", heuristic.heuristic_id);
44 Ok(())
45 }
46
47 pub async fn get_heuristic(&self, id: Uuid) -> Result<Option<Heuristic>> {
49 debug!("Retrieving heuristic: {}", id);
50 let (conn, _conn_id) = self.get_connection_with_id().await?;
51
52 const SQL: &str = r#"
53 SELECT heuristic_id, condition_text, action_text, confidence, evidence, created_at, updated_at
54 FROM heuristics WHERE heuristic_id = ?
55 "#;
56
57 let stmt = self
59 .prepared_cache
60 .get_or_prepare(&conn, SQL)
61 .await
62 .map_err(|e| Error::Storage(format!("Failed to prepare statement: {}", e)))?;
63
64 let mut rows = stmt
65 .query(libsql::params![id.to_string()])
66 .await
67 .map_err(|e| Error::Storage(format!("Failed to query heuristic: {}", e)))?;
68
69 if let Some(row) = rows
70 .next()
71 .await
72 .map_err(|e| Error::Storage(format!("Failed to fetch heuristic row: {}", e)))?
73 {
74 let heuristic = row_to_heuristic(&row)?;
75 Ok(Some(heuristic))
76 } else {
77 Ok(None)
78 }
79 }
80
81 pub async fn get_heuristics(&self) -> Result<Vec<Heuristic>> {
83 debug!("Retrieving all heuristics");
84 let (conn, _conn_id) = self.get_connection_with_id().await?;
85
86 const SQL: &str = r#"
87 SELECT heuristic_id, condition_text, action_text, confidence, evidence, created_at, updated_at
88 FROM heuristics ORDER BY confidence DESC
89 "#;
90
91 let stmt = self
93 .prepared_cache
94 .get_or_prepare(&conn, SQL)
95 .await
96 .map_err(|e| Error::Storage(format!("Failed to prepare statement: {}", e)))?;
97
98 let mut rows = stmt
99 .query(())
100 .await
101 .map_err(|e| Error::Storage(format!("Failed to query heuristics: {}", e)))?;
102
103 let mut heuristics = Vec::new();
104 while let Some(row) = rows
105 .next()
106 .await
107 .map_err(|e| Error::Storage(format!("Failed to fetch heuristic row: {}", e)))?
108 {
109 heuristics.push(row_to_heuristic(&row)?);
110 }
111
112 info!("Found {} heuristics", heuristics.len());
113 Ok(heuristics)
114 }
115
116 pub async fn delete_heuristic(&self, id: Uuid) -> Result<()> {
118 debug!("Deleting heuristic: {}", id);
119 let (conn, _conn_id) = self.get_connection_with_id().await?;
120
121 const SQL: &str = "DELETE FROM heuristics WHERE heuristic_id = ?";
122
123 let stmt = self
125 .prepared_cache
126 .get_or_prepare(&conn, SQL)
127 .await
128 .map_err(|e| Error::Storage(format!("Failed to prepare statement: {}", e)))?;
129
130 stmt.execute(libsql::params![id.to_string()])
131 .await
132 .map_err(|e| Error::Storage(format!("Failed to delete heuristic: {}", e)))?;
133
134 info!("Successfully deleted heuristic: {}", id);
135 Ok(())
136 }
137}
138
139pub fn row_to_heuristic(row: &Row) -> Result<Heuristic> {
141 let id: String = row.get(0).map_err(|e| Error::Storage(e.to_string()))?;
142 let heuristic_id = Uuid::parse_str(&id).map_err(|e| Error::Storage(e.to_string()))?;
143 let condition: String = row.get(1).map_err(|e| Error::Storage(e.to_string()))?;
144 let action: String = row.get(2).map_err(|e| Error::Storage(e.to_string()))?;
145 let confidence: f64 = row.get(3).map_err(|e| Error::Storage(e.to_string()))?;
146 let evidence_json: String = row.get(4).map_err(|e| Error::Storage(e.to_string()))?;
147 let created_at_timestamp: i64 = row.get(5).map_err(|e| Error::Storage(e.to_string()))?;
148 let updated_at_timestamp: i64 = row.get(6).map_err(|e| Error::Storage(e.to_string()))?;
149
150 let evidence: do_memory_core::types::Evidence = serde_json::from_str(&evidence_json)
151 .map_err(|e| Error::Storage(format!("Failed to parse evidence: {}", e)))?;
152
153 Ok(Heuristic {
154 heuristic_id,
155 condition,
156 action,
157 confidence: confidence as f32,
158 evidence,
159 created_at: chrono::DateTime::from_timestamp(created_at_timestamp, 0).unwrap_or_default(),
160 updated_at: chrono::DateTime::from_timestamp(updated_at_timestamp, 0).unwrap_or_default(),
161 })
162}