kaizen/store/sqlite/
feedback.rs1use super::rows::*;
2use super::*;
3
4impl Store {
5 pub fn upsert_feedback(&self, r: &crate::feedback::types::FeedbackRecord) -> Result<()> {
6 use crate::feedback::types::FeedbackLabel;
7 self.conn.execute(
8 "INSERT OR REPLACE INTO session_feedback
9 (id, session_id, score, label, note, created_at_ms)
10 VALUES (?1, ?2, ?3, ?4, ?5, ?6)",
11 rusqlite::params![
12 r.id,
13 r.session_id,
14 r.score.as_ref().map(|s| s.0 as i64),
15 r.label.as_ref().map(FeedbackLabel::to_db_str),
16 r.note,
17 r.created_at_ms as i64,
18 ],
19 )?;
20 let payload = serde_json::to_string(r).unwrap_or_default();
21 self.conn.execute(
22 "INSERT INTO sync_outbox (session_id, kind, payload, sent)
23 VALUES (?1, 'session_feedback', ?2, 0)",
24 rusqlite::params![r.session_id, payload],
25 )?;
26 Ok(())
27 }
28
29 pub fn list_feedback_in_window(
30 &self,
31 start_ms: u64,
32 end_ms: u64,
33 ) -> Result<Vec<crate::feedback::types::FeedbackRecord>> {
34 let mut stmt = self.conn.prepare(
35 "SELECT id, session_id, score, label, note, created_at_ms
36 FROM session_feedback
37 WHERE created_at_ms >= ?1 AND created_at_ms < ?2
38 ORDER BY created_at_ms ASC",
39 )?;
40 let rows = stmt.query_map(
41 rusqlite::params![start_ms as i64, end_ms as i64],
42 feedback_row,
43 )?;
44 rows.map(|r| r.map_err(anyhow::Error::from)).collect()
45 }
46
47 pub fn feedback_for_sessions(
48 &self,
49 ids: &[String],
50 ) -> Result<std::collections::HashMap<String, crate::feedback::types::FeedbackRecord>> {
51 if ids.is_empty() {
52 return Ok(std::collections::HashMap::new());
53 }
54 let placeholders = ids.iter().map(|_| "?").collect::<Vec<_>>().join(",");
55 let sql = format!(
56 "SELECT id, session_id, score, label, note, created_at_ms
57 FROM session_feedback WHERE session_id IN ({placeholders})
58 ORDER BY created_at_ms DESC"
59 );
60 let mut stmt = self.conn.prepare(&sql)?;
61 let params: Vec<&dyn rusqlite::ToSql> =
62 ids.iter().map(|s| s as &dyn rusqlite::ToSql).collect();
63 let rows = stmt.query_map(params.as_slice(), feedback_row)?;
64 let mut map = std::collections::HashMap::new();
65 for row in rows {
66 let r = row?;
67 map.entry(r.session_id.clone()).or_insert(r);
68 }
69 Ok(map)
70 }
71}