pub mod agents;
pub mod attachments;
pub mod dashboard;
pub mod deps;
pub mod export;
pub mod import;
pub mod locks;
pub mod schema;
pub mod search;
pub mod state_transitions;
pub mod stats;
pub mod tasks;
pub use deps::AddDependencyResult;
pub use search::{AttachmentMatch, SearchResult};
use anyhow::Result;
use rusqlite::Connection;
use std::path::Path;
use std::sync::{Arc, Mutex};
mod embedded {
use refinery::embed_migrations;
embed_migrations!("migrations");
}
#[derive(Clone)]
pub struct Database {
conn: Arc<Mutex<Connection>>,
}
impl Database {
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
let conn = Connection::open(path)?;
conn.execute_batch(
"PRAGMA journal_mode=WAL;
PRAGMA foreign_keys=ON;
PRAGMA busy_timeout=5000;",
)?;
let db = Self {
conn: Arc::new(Mutex::new(conn)),
};
db.run_migrations()?;
Ok(db)
}
#[allow(dead_code)]
pub fn open_in_memory() -> Result<Self> {
let conn = Connection::open_in_memory()?;
conn.execute_batch("PRAGMA foreign_keys=ON;")?;
let db = Self {
conn: Arc::new(Mutex::new(conn)),
};
db.run_migrations()?;
Ok(db)
}
fn run_migrations(&self) -> Result<()> {
let mut conn = self.conn.lock().unwrap_or_else(|e| e.into_inner());
embedded::migrations::runner().run(&mut *conn)?;
Ok(())
}
pub fn with_conn<F, T>(&self, f: F) -> Result<T>
where
F: FnOnce(&Connection) -> Result<T>,
{
let conn = self.conn.lock().unwrap_or_else(|e| e.into_inner());
f(&conn)
}
pub fn with_conn_mut<F, T>(&self, f: F) -> Result<T>
where
F: FnOnce(&mut Connection) -> Result<T>,
{
let mut conn = self.conn.lock().unwrap_or_else(|e| e.into_inner());
f(&mut conn)
}
}
pub fn now_ms() -> i64 {
chrono::Utc::now().timestamp_millis()
}