vector_core/db/
id_cache.rs1use std::collections::HashMap;
7use std::sync::{Arc, RwLock};
8
9struct ChatIds;
13struct UserIds;
14
15fn chat_id_cache() -> Arc<RwLock<HashMap<String, i64>>> {
16 crate::db::current_session().scoped::<ChatIds, _>()
17}
18
19fn user_id_cache() -> Arc<RwLock<HashMap<String, i64>>> {
20 crate::db::current_session().scoped::<UserIds, _>()
21}
22
23pub fn forget_chat_id(chat_identifier: &str) {
26 chat_id_cache().write().unwrap().remove(chat_identifier);
27}
28
29pub fn get_chat_id_by_identifier(chat_identifier: &str) -> Result<i64, String> {
31 {
33 let owner = chat_id_cache();
34 let cache = owner.read().unwrap();
35 if let Some(&id) = cache.get(chat_identifier) {
36 return Ok(id);
37 }
38 }
39
40 let conn = super::get_db_connection_guard_static()?;
42 let id: i64 = conn.query_row(
43 "SELECT id FROM chats WHERE chat_identifier = ?1",
44 rusqlite::params![chat_identifier],
45 |row| row.get(0)
46 ).map_err(|_| format!("Chat not found: {}", chat_identifier))?;
47
48 {
50 let owner = chat_id_cache();
51 let mut cache = owner.write().unwrap();
52 cache.insert(chat_identifier.to_string(), id);
53 }
54
55 Ok(id)
56}
57
58pub fn get_or_create_chat_id(chat_identifier: &str) -> Result<i64, String> {
60 {
62 let owner = chat_id_cache();
63 let cache = owner.read().unwrap();
64 if let Some(&id) = cache.get(chat_identifier) {
65 return Ok(id);
66 }
67 }
68
69 let conn = super::get_db_connection_guard_static()?;
70
71 let existing: Option<i64> = conn.query_row(
73 "SELECT id FROM chats WHERE chat_identifier = ?1",
74 rusqlite::params![chat_identifier],
75 |row| row.get(0)
76 ).ok();
77
78 let id = if let Some(id) = existing {
79 id
80 } else {
81 let now = std::time::SystemTime::now()
86 .duration_since(std::time::UNIX_EPOCH).unwrap()
87 .as_secs() as i64;
88 let chat_type: i32 = if chat_identifier.starts_with("npub1") { 0 } else { 2 };
89
90 let participants = if chat_type == 0 {
94 format!("[\"{}\"]", chat_identifier)
95 } else {
96 "[]".to_string()
97 };
98
99 conn.execute(
100 "INSERT INTO chats (chat_identifier, chat_type, participants, created_at) VALUES (?1, ?2, ?3, ?4)",
101 rusqlite::params![chat_identifier, chat_type, participants, now],
102 ).map_err(|e| format!("Failed to create chat stub: {}", e))?;
103
104 conn.last_insert_rowid()
105 };
106
107 {
109 let owner = chat_id_cache();
110 let mut cache = owner.write().unwrap();
111 cache.insert(chat_identifier.to_string(), id);
112 }
113
114 Ok(id)
115}
116
117pub fn get_or_create_user_id(npub: &str) -> Result<Option<i64>, String> {
119 if npub.is_empty() {
120 return Ok(None);
121 }
122
123 {
125 let owner = user_id_cache();
126 let cache = owner.read().unwrap();
127 if let Some(&id) = cache.get(npub) {
128 return Ok(Some(id));
129 }
130 }
131
132 let conn = super::get_db_connection_guard_static()?;
133
134 let existing: Option<i64> = conn.query_row(
135 "SELECT id FROM profiles WHERE npub = ?1",
136 rusqlite::params![npub],
137 |row| row.get(0)
138 ).ok();
139
140 let id = if let Some(id) = existing {
141 id
142 } else {
143 conn.execute(
144 "INSERT INTO profiles (npub, name, display_name) VALUES (?1, '', '')",
145 rusqlite::params![npub],
146 ).map_err(|e| format!("Failed to create profile stub: {}", e))?;
147 conn.last_insert_rowid()
148 };
149
150 {
152 let owner = user_id_cache();
153 let mut cache = owner.write().unwrap();
154 cache.insert(npub.to_string(), id);
155 }
156
157 Ok(Some(id))
158}
159
160pub fn preload_id_caches() -> Result<(), String> {
162 let conn = match super::get_db_connection_guard_static() {
163 Ok(c) => c,
164 Err(_) => return Ok(()), };
166
167 {
169 let mut stmt = conn.prepare("SELECT chat_identifier, id FROM chats")
170 .map_err(|e| format!("Failed to prepare chat query: {}", e))?;
171 let rows = stmt.query_map([], |row| {
172 Ok((row.get::<_, String>(0)?, row.get::<_, i64>(1)?))
173 }).map_err(|e| format!("Failed to query chats: {}", e))?;
174
175 let owner = chat_id_cache();
176 let mut cache = owner.write().unwrap();
177 for row in rows.flatten() {
178 cache.insert(row.0, row.1);
179 }
180 }
181
182 {
184 let mut stmt = conn.prepare("SELECT npub, id FROM profiles")
185 .map_err(|e| format!("Failed to prepare user query: {}", e))?;
186 let rows = stmt.query_map([], |row| {
187 Ok((row.get::<_, String>(0)?, row.get::<_, i64>(1)?))
188 }).map_err(|e| format!("Failed to query profiles: {}", e))?;
189
190 let owner = user_id_cache();
191 let mut cache = owner.write().unwrap();
192 for row in rows.flatten() {
193 cache.insert(row.0, row.1);
194 }
195 }
196
197 Ok(())
198}
199
200pub fn clear_id_caches() {
202 chat_id_cache().write().unwrap().clear();
203 user_id_cache().write().unwrap().clear();
204}