-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
automatically create database file on startup
- Loading branch information
Showing
14 changed files
with
265 additions
and
122 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
150 changes: 150 additions & 0 deletions
150
lumni/src/apps/builtin/llm/prompt/src/chat/db/connector.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
use std::collections::{HashMap, VecDeque}; | ||
use std::path::PathBuf; | ||
use std::sync::{Arc, Mutex}; | ||
use std::thread; | ||
|
||
use rusqlite::{ | ||
params, Connection, Error as SqliteError, Result as SqliteResult, | ||
}; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
use super::schema::{ | ||
Attachment, AttachmentData, Conversation, Exchange, Message, | ||
}; | ||
|
||
pub struct DatabaseConnector { | ||
connection: rusqlite::Connection, | ||
operation_queue: Arc<Mutex<VecDeque<String>>>, | ||
} | ||
|
||
impl DatabaseConnector { | ||
const SCHEMA_SQL: &'static str = include_str!("schema.sql"); | ||
const EXPECTED_VERSION: &'static str = "1"; | ||
const EXPECTED_IDENTIFIER: &'static str = "prompt.chat"; | ||
|
||
pub fn new(sqlite_file: &PathBuf) -> Result<Self, SqliteError> { | ||
let connection = rusqlite::Connection::open(sqlite_file)?; | ||
let operation_queue = Arc::new(Mutex::new(VecDeque::new())); | ||
|
||
let mut conn = DatabaseConnector { | ||
connection, | ||
operation_queue, | ||
}; | ||
conn.initialize_schema()?; | ||
Ok(conn) | ||
} | ||
|
||
fn initialize_schema(&mut self) -> Result<(), SqliteError> { | ||
let transaction = self.connection.transaction()?; | ||
|
||
// Check if the metadata table exists and has the correct version and identifier | ||
let (version, identifier, need_initialization) = { | ||
let mut stmt = transaction.prepare( | ||
"SELECT key, value FROM metadata WHERE key IN \ | ||
('schema_version', 'schema_identifier')", | ||
); | ||
|
||
match stmt { | ||
Ok(ref mut stmt) => { | ||
let result: Result<Vec<(String, String)>, rusqlite::Error> = | ||
stmt.query_map([], |row| { | ||
Ok((row.get(0)?, row.get(1)?)) | ||
})? | ||
.collect(); | ||
|
||
let mut version = None; | ||
let mut identifier = None; | ||
|
||
match result { | ||
Ok(rows) if !rows.is_empty() => { | ||
for (key, value) in rows { | ||
match key.as_str() { | ||
"schema_version" => version = Some(value), | ||
"schema_identifier" => { | ||
identifier = Some(value) | ||
} | ||
_ => {} | ||
} | ||
} | ||
eprintln!( | ||
"Version: {:?}, Identifier: {:?}", | ||
version, identifier | ||
); | ||
(version, identifier, false) | ||
} | ||
Ok(_) | Err(SqliteError::QueryReturnedNoRows) => { | ||
eprintln!( | ||
"No schema version or identifier found. Need \ | ||
initialization." | ||
); | ||
(None, None, true) | ||
} | ||
Err(e) => return Err(e), | ||
} | ||
} | ||
Err(e) => match e { | ||
SqliteError::SqliteFailure(_, Some(ref error_string)) | ||
if error_string.contains("no such table") => | ||
{ | ||
eprintln!( | ||
"No metadata table found. Need to create the \ | ||
schema." | ||
); | ||
(None, None, true) | ||
} | ||
_ => return Err(e), | ||
}, | ||
} | ||
}; | ||
|
||
if need_initialization { | ||
eprintln!("Initializing database schema..."); | ||
transaction.execute_batch(Self::SCHEMA_SQL)?; | ||
transaction.execute( | ||
"INSERT INTO metadata (key, value) VALUES ('schema_version', \ | ||
?1), ('schema_identifier', ?2)", | ||
params![Self::EXPECTED_VERSION, Self::EXPECTED_IDENTIFIER], | ||
)?; | ||
eprintln!( | ||
"Schema version and identifier metadata initialized \ | ||
successfully." | ||
); | ||
} else if let (Some(v), Some(i)) = (version, identifier) { | ||
if v == Self::EXPECTED_VERSION && i == Self::EXPECTED_IDENTIFIER { | ||
eprintln!("Database schema is up to date (version {}).", v); | ||
} else { | ||
eprintln!( | ||
"Found existing schema version {} for app {}. Expected \ | ||
version {} for {}.", | ||
v, | ||
i, | ||
Self::EXPECTED_VERSION, | ||
Self::EXPECTED_IDENTIFIER | ||
); | ||
return Err(SqliteError::SqliteFailure( | ||
rusqlite::ffi::Error::new(1), // 1 is SQLITE_ERROR | ||
Some("Schema version mismatch".to_string()), | ||
)); | ||
} | ||
} | ||
transaction.commit()?; | ||
Ok(()) | ||
} | ||
|
||
pub fn queue_operation(&self, sql: String) { | ||
let mut queue = self.operation_queue.lock().unwrap(); | ||
queue.push_back(sql); | ||
} | ||
|
||
pub fn process_queue(&mut self) -> Result<(), rusqlite::Error> { | ||
let mut queue = self.operation_queue.lock().unwrap(); | ||
let tx = self.connection.transaction()?; | ||
|
||
while let Some(sql) = queue.pop_front() { | ||
tx.execute(&sql, [])?; | ||
} | ||
|
||
tx.commit()?; | ||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
mod connector; | ||
mod schema; | ||
|
||
pub use connector::DatabaseConnector; | ||
pub use schema::{ | ||
ConversationId, Exchange, InMemoryDatabase, Message, ModelId, | ||
}; | ||
|
||
pub use super::PromptRole; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.