offline_intelligence/memory_db/
session_file_contexts_store.rs1use anyhow::Result;
8use r2d2::Pool;
9use r2d2_sqlite::SqliteConnectionManager;
10use std::sync::Arc;
11use tracing::{debug, info};
12
13#[derive(Debug, Clone)]
15pub struct SessionFileContext {
16 pub id: i64,
17 pub session_id: String,
18 pub file_name: String,
19 pub source: String,
21 pub file_path: Option<String>,
23 pub all_files_id: Option<i64>,
25 pub size_bytes: Option<i64>,
26}
27
28pub struct AttachmentRef<'a> {
31 pub name: &'a str,
32 pub source: &'a str,
33 pub file_path: Option<&'a str>,
34 pub all_files_id: Option<i64>,
35 pub size_bytes: Option<i64>,
36}
37
38pub struct SessionFileContextsStore {
39 pool: Arc<Pool<SqliteConnectionManager>>,
40}
41
42impl SessionFileContextsStore {
43 pub fn new(pool: Arc<Pool<SqliteConnectionManager>>) -> Self {
44 Self { pool }
45 }
46
47 pub fn store_attachments(
51 &self,
52 session_id: &str,
53 attachments: &[AttachmentRef<'_>],
54 ) -> Result<()> {
55 let conn = self.pool.get()?;
56 for att in attachments {
57 conn.execute(
58 "INSERT OR IGNORE INTO session_file_contexts
59 (session_id, file_name, source, file_path, all_files_id, size_bytes)
60 VALUES (?1, ?2, ?3, ?4, ?5, ?6)",
61 rusqlite::params![
62 session_id,
63 att.name,
64 att.source,
65 att.file_path,
66 att.all_files_id,
67 att.size_bytes,
68 ],
69 )?;
70 }
71 debug!(
72 "Stored {} attachment reference(s) for session {}",
73 attachments.len(),
74 session_id
75 );
76 Ok(())
77 }
78
79 pub fn get_for_session(&self, session_id: &str) -> Result<Vec<SessionFileContext>> {
81 let conn = self.pool.get()?;
82 let mut stmt = conn.prepare(
83 "SELECT id, session_id, file_name, source, file_path, all_files_id, size_bytes
84 FROM session_file_contexts
85 WHERE session_id = ?1
86 ORDER BY attached_at ASC",
87 )?;
88
89 let rows = stmt.query_map([session_id], |row| {
90 Ok(SessionFileContext {
91 id: row.get(0)?,
92 session_id: row.get(1)?,
93 file_name: row.get(2)?,
94 source: row.get(3)?,
95 file_path: row.get(4)?,
96 all_files_id: row.get(5)?,
97 size_bytes: row.get(6)?,
98 })
99 })?;
100
101 let mut results = Vec::new();
102 for row in rows {
103 results.push(row?);
104 }
105
106 info!(
107 "Retrieved {} historical attachment(s) for session {}",
108 results.len(),
109 session_id
110 );
111 Ok(results)
112 }
113
114 pub fn delete_for_session(&self, session_id: &str) -> Result<usize> {
116 let conn = self.pool.get()?;
117 let n = conn.execute(
118 "DELETE FROM session_file_contexts WHERE session_id = ?1",
119 [session_id],
120 )?;
121 Ok(n)
122 }
123}