vector_core/db/
id_cache.rs1use std::collections::HashMap;
7use std::sync::{Arc, LazyLock, RwLock};
8
9static CHAT_ID_CACHE: LazyLock<Arc<RwLock<HashMap<String, i64>>>> =
10 LazyLock::new(|| Arc::new(RwLock::new(HashMap::new())));
11
12static USER_ID_CACHE: LazyLock<Arc<RwLock<HashMap<String, i64>>>> =
13 LazyLock::new(|| Arc::new(RwLock::new(HashMap::new())));
14
15pub fn forget_chat_id(chat_identifier: &str) {
18 CHAT_ID_CACHE.write().unwrap().remove(chat_identifier);
19}
20
21pub fn get_chat_id_by_identifier(chat_identifier: &str) -> Result<i64, String> {
23 {
25 let cache = CHAT_ID_CACHE.read().unwrap();
26 if let Some(&id) = cache.get(chat_identifier) {
27 return Ok(id);
28 }
29 }
30
31 let conn = super::get_db_connection_guard_static()?;
33 let id: i64 = conn.query_row(
34 "SELECT id FROM chats WHERE chat_identifier = ?1",
35 rusqlite::params![chat_identifier],
36 |row| row.get(0)
37 ).map_err(|_| format!("Chat not found: {}", chat_identifier))?;
38
39 {
41 let mut cache = CHAT_ID_CACHE.write().unwrap();
42 cache.insert(chat_identifier.to_string(), id);
43 }
44
45 Ok(id)
46}
47
48pub fn get_or_create_chat_id(chat_identifier: &str) -> Result<i64, String> {
50 {
52 let cache = CHAT_ID_CACHE.read().unwrap();
53 if let Some(&id) = cache.get(chat_identifier) {
54 return Ok(id);
55 }
56 }
57
58 let conn = super::get_db_connection_guard_static()?;
59
60 let existing: Option<i64> = conn.query_row(
62 "SELECT id FROM chats WHERE chat_identifier = ?1",
63 rusqlite::params![chat_identifier],
64 |row| row.get(0)
65 ).ok();
66
67 let id = if let Some(id) = existing {
68 id
69 } else {
70 let now = std::time::SystemTime::now()
75 .duration_since(std::time::UNIX_EPOCH).unwrap()
76 .as_secs() as i64;
77 let chat_type: i32 = if chat_identifier.starts_with("npub1") { 0 } else { 2 };
78
79 conn.execute(
80 "INSERT INTO chats (chat_identifier, chat_type, participants, created_at) VALUES (?1, ?2, '[]', ?3)",
81 rusqlite::params![chat_identifier, chat_type, now],
82 ).map_err(|e| format!("Failed to create chat stub: {}", e))?;
83
84 conn.last_insert_rowid()
85 };
86
87 {
89 let mut cache = CHAT_ID_CACHE.write().unwrap();
90 cache.insert(chat_identifier.to_string(), id);
91 }
92
93 Ok(id)
94}
95
96pub fn get_or_create_user_id(npub: &str) -> Result<Option<i64>, String> {
98 if npub.is_empty() {
99 return Ok(None);
100 }
101
102 {
104 let cache = USER_ID_CACHE.read().unwrap();
105 if let Some(&id) = cache.get(npub) {
106 return Ok(Some(id));
107 }
108 }
109
110 let conn = super::get_db_connection_guard_static()?;
111
112 let existing: Option<i64> = conn.query_row(
113 "SELECT id FROM profiles WHERE npub = ?1",
114 rusqlite::params![npub],
115 |row| row.get(0)
116 ).ok();
117
118 let id = if let Some(id) = existing {
119 id
120 } else {
121 conn.execute(
122 "INSERT INTO profiles (npub, name, display_name) VALUES (?1, '', '')",
123 rusqlite::params![npub],
124 ).map_err(|e| format!("Failed to create profile stub: {}", e))?;
125 conn.last_insert_rowid()
126 };
127
128 {
130 let mut cache = USER_ID_CACHE.write().unwrap();
131 cache.insert(npub.to_string(), id);
132 }
133
134 Ok(Some(id))
135}
136
137pub fn preload_id_caches() -> Result<(), String> {
139 let conn = match super::get_db_connection_guard_static() {
140 Ok(c) => c,
141 Err(_) => return Ok(()), };
143
144 {
146 let mut stmt = conn.prepare("SELECT chat_identifier, id FROM chats")
147 .map_err(|e| format!("Failed to prepare chat query: {}", e))?;
148 let rows = stmt.query_map([], |row| {
149 Ok((row.get::<_, String>(0)?, row.get::<_, i64>(1)?))
150 }).map_err(|e| format!("Failed to query chats: {}", e))?;
151
152 let mut cache = CHAT_ID_CACHE.write().unwrap();
153 for row in rows.flatten() {
154 cache.insert(row.0, row.1);
155 }
156 }
157
158 {
160 let mut stmt = conn.prepare("SELECT npub, id FROM profiles")
161 .map_err(|e| format!("Failed to prepare user query: {}", e))?;
162 let rows = stmt.query_map([], |row| {
163 Ok((row.get::<_, String>(0)?, row.get::<_, i64>(1)?))
164 }).map_err(|e| format!("Failed to query profiles: {}", e))?;
165
166 let mut cache = USER_ID_CACHE.write().unwrap();
167 for row in rows.flatten() {
168 cache.insert(row.0, row.1);
169 }
170 }
171
172 Ok(())
173}
174
175pub fn clear_id_caches() {
177 CHAT_ID_CACHE.write().unwrap().clear();
178 USER_ID_CACHE.write().unwrap().clear();
179}