A local-first private AI assistant for everyday use. Runs on-device models with encrypted P2P sync, and supports sharing chats publicly on ATProto.
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: Added apply_delta for bulk inserts of delta chat rows

madclaws d74caebb 10ceca31

+50 -15
+50 -15
tiles/src/core/chats.rs
··· 9 9 use crate::runtime::mlx::ChatResponse; 10 10 use crate::utils::get_unix_time_now; 11 11 use anyhow::Result; 12 - use rusqlite::Connection; 13 12 use rusqlite::types::FromSqlError; 13 + use rusqlite::{Connection, params}; 14 14 use tilekit::modelfile::Role; 15 15 use uuid::Uuid; 16 16 // model the chats table ··· 55 55 input: &str, 56 56 chat_resp: Option<&ChatResponse>, 57 57 ) -> Result<Chats> { 58 - let row_counter = get_last_row_counter(&conn, &user.user_id)?; 58 + let row_counter = get_last_row_counter(conn, &user.user_id)?; 59 59 if let Some(chat_response) = chat_resp { 60 60 let chat_resp_cloned = chat_response.clone(); 61 61 ··· 124 124 } 125 125 /// Return list of rows.. 126 126 /// encoding is the job of network modules 127 - pub fn get_delta_since_id( 128 - conn: &Connection, 129 - user_id: &str, 130 - last_entry_id: &str, 131 - ) -> Result<Vec<Chats>> { 132 - let mut stmt = conn.prepare("select id, user_id, content, resp_id, role, context_id, created_at, updated_at , row_counter from chats where user_id = ?1 and id > ?2 order by id")?; 127 + pub fn get_delta(conn: &Connection, user_id: &str, last_row_couter: i64) -> Result<Vec<Chats>> { 128 + let mut stmt = conn.prepare("select id, user_id, content, resp_id, role, context_id, created_at, updated_at , row_counter from chats where user_id = ?1 and row_counter > ?2 order by id")?; 133 129 134 - let chat_rows = stmt.query_map([user_id, last_entry_id], |row| { 130 + let chat_rows = stmt.query_map(params![user_id, last_row_couter], |row| { 135 131 let id: String = row.get(0)?; 136 132 let role: String = row.get(4)?; 137 133 let created_at: f64 = row.get(6)?; ··· 160 156 Ok(chats) 161 157 } 162 158 163 - fn apply_delta() -> Result<()> { 159 + pub fn apply_delta(chat_conn: &mut Connection, delta_chats: Vec<Chats>) -> Result<()> { 164 160 // bulk insert 161 + // TODO: Handle primary key conflict, for now upsert it, later 162 + // do LWW based on iss of UCAN 163 + let txn = chat_conn.transaction()?; 164 + { 165 + let mut stmt = txn.prepare("insert into chats(id, user_id, content, resp_id, role, context_id, created_at, updated_at, row_counter) values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)")?; 165 166 166 - unimplemented!() 167 + for chat in delta_chats { 168 + stmt.execute(params![ 169 + &chat.id.to_string(), 170 + &chat.user_id, 171 + &chat.content, 172 + &chat.response_id, 173 + Into::<String>::into(chat.role), 174 + &chat.context_id, 175 + &chat.created_at.to_string(), 176 + &chat.updated_at.to_string(), 177 + &chat.row_counter, 178 + ])?; 179 + } 180 + } 181 + txn.commit()?; 182 + 183 + Ok(()) 167 184 } 168 185 169 186 #[cfg(test)] ··· 177 194 use crate::{ 178 195 core::{ 179 196 accounts::{ACCOUNT, User}, 180 - chats::{get_delta_since_id, get_last_row_counter, save_chat}, 197 + chats::{apply_delta, get_delta, get_last_row_counter, save_chat}, 181 198 }, 182 199 runtime::mlx::ChatResponse, 183 200 }; ··· 304 321 let _ = save_chat(&conn, &user, input, None).expect("chat should be saved"); 305 322 let _ = save_chat(&conn, &user, input, None).expect("chat should be saved"); 306 323 307 - let rows = get_delta_since_id(&conn, &user.user_id, &chat_1.id.to_string()).unwrap(); 324 + let rows = get_delta(&conn, &user.user_id, chat_1.row_counter).unwrap(); 308 325 assert_eq!(rows.len(), 3); 309 326 } 310 327 ··· 318 335 let _ = save_chat(&conn, &user, input, None).expect("chat should be saved"); 319 336 let _ = save_chat(&conn, &user, input, None).expect("chat should be saved"); 320 337 321 - let rows = get_delta_since_id(&conn, &user.user_id, "").unwrap(); 338 + let rows = get_delta(&conn, &user.user_id, 0).unwrap(); 322 339 assert_eq!(rows.len(), 4); 323 340 } 324 341 ··· 332 349 let _ = save_chat(&conn, &user, input, None).expect("chat should be saved"); 333 350 let _ = save_chat(&conn, &user, input, None).expect("chat should be saved"); 334 351 335 - let rows = get_delta_since_id(&conn, "", "").unwrap(); 352 + let rows = get_delta(&conn, "", 0).unwrap(); 336 353 assert_eq!(rows.len(), 0); 354 + } 355 + 356 + #[test] 357 + fn test_apply_delta() { 358 + let conn = setup_db_schema(); 359 + let mut conn_2 = setup_db_schema(); 360 + let user = create_user(); 361 + let input = "2+2"; 362 + let _chat_1 = save_chat(&conn, &user, input, None).expect("chat should be saved"); 363 + let _ = save_chat(&conn, &user, input, None).expect("chat should be saved"); 364 + let _ = save_chat(&conn, &user, input, None).expect("chat should be saved"); 365 + let _ = save_chat(&conn, &user, input, None).expect("chat should be saved"); 366 + 367 + let rows = get_delta(&conn, &user.user_id, 0).unwrap(); 368 + assert_eq!(rows.len(), 4); 369 + assert!(apply_delta(&mut conn_2, rows).is_ok()); 370 + let rows = get_delta(&conn_2, &user.user_id, 0).unwrap(); 371 + assert_eq!(rows.len(), 4); 337 372 } 338 373 339 374 struct SavedChatRow {