entrenar/storage/sqlite/backend/
sqlite_backend.rs1use super::schema;
7use crate::storage::Result;
8use crate::storage::StorageError;
9use rusqlite::Connection;
10use std::path::Path;
11use std::sync::Mutex;
12
13pub struct SqliteBackend {
23 pub(crate) conn: Mutex<Connection>,
24 pub(crate) path: String,
25}
26
27impl std::fmt::Debug for SqliteBackend {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 f.debug_struct("SqliteBackend").field("path", &self.path).finish_non_exhaustive()
31 }
32}
33
34impl SqliteBackend {
35 pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
37 let path_str = path.as_ref().to_string_lossy().to_string();
38 let conn = Connection::open(path.as_ref())
39 .map_err(|e| StorageError::Backend(format!("Failed to open SQLite database: {e}")))?;
40 schema::init_schema(&conn)
41 .map_err(|e| StorageError::Backend(format!("Failed to initialize schema: {e}")))?;
42 Ok(Self { conn: Mutex::new(conn), path: path_str })
43 }
44
45 pub fn open_in_memory() -> Result<Self> {
47 let conn = Connection::open_in_memory()
48 .map_err(|e| StorageError::Backend(format!("Failed to open in-memory SQLite: {e}")))?;
49 schema::init_schema(&conn)
50 .map_err(|e| StorageError::Backend(format!("Failed to initialize schema: {e}")))?;
51 Ok(Self { conn: Mutex::new(conn), path: ":memory:".to_string() })
52 }
53
54 pub fn open_project<P: AsRef<Path>>(project_dir: P) -> Result<Self> {
56 let dir = project_dir.as_ref().join(".entrenar");
57 std::fs::create_dir_all(&dir)?;
58 Self::open(dir.join("experiments.db"))
59 }
60
61 pub fn path(&self) -> &str {
63 &self.path
64 }
65
66 pub(crate) fn generate_id() -> String {
68 use std::time::{SystemTime, UNIX_EPOCH};
69 let ts = SystemTime::now()
70 .duration_since(UNIX_EPOCH)
71 .expect("system clock must not be before UNIX epoch")
72 .as_nanos();
73 format!("{ts:x}")
74 }
75
76 pub(crate) fn lock_conn(
78 &self,
79 ) -> std::result::Result<std::sync::MutexGuard<'_, Connection>, StorageError> {
80 self.conn
81 .lock()
82 .map_err(|e| StorageError::Backend(format!("Failed to acquire connection lock: {e}")))
83 }
84}