use crate::{OverDriveDB, QueryResult};
use crate::result::{SdkResult, SdkError};
use serde_json::Value;
use std::sync::{Arc, Mutex};
#[derive(Clone)]
pub struct SharedDB {
inner: Arc<Mutex<OverDriveDB>>,
}
impl SharedDB {
pub fn open(path: &str) -> SdkResult<Self> {
let db = OverDriveDB::open(path)?;
Ok(Self {
inner: Arc::new(Mutex::new(db)),
})
}
pub fn open_encrypted(path: &str, key_env_var: &str) -> SdkResult<Self> {
let db = OverDriveDB::open_encrypted(path, key_env_var)?;
Ok(Self {
inner: Arc::new(Mutex::new(db)),
})
}
pub fn with<F, T>(&self, f: F) -> SdkResult<T>
where
F: FnOnce(&mut OverDriveDB) -> T,
{
let mut guard = self.inner.lock().map_err(|_| {
SdkError::SecurityError(
"SharedDB mutex is poisoned — a thread panicked while holding the lock. \
Create a new SharedDB instance to recover.".to_string()
)
})?;
Ok(f(&mut guard))
}
pub fn query(&self, sql: &str) -> SdkResult<QueryResult> {
self.with(|db| db.query(sql))?
}
pub fn query_safe(&self, sql_template: &str, params: &[&str]) -> SdkResult<QueryResult> {
self.with(|db| db.query_safe(sql_template, params))?
}
pub fn insert(&self, table: &str, doc: &Value) -> SdkResult<String> {
self.with(|db| db.insert(table, doc))?
}
pub fn get(&self, table: &str, id: &str) -> SdkResult<Option<Value>> {
self.with(|db| db.get(table, id))?
}
pub fn backup(&self, dest_path: &str) -> SdkResult<()> {
self.with(|db| db.backup(dest_path))?
}
pub fn sync(&self) -> SdkResult<()> {
self.with(|db| db.sync())?
}
pub fn handle_count(&self) -> usize {
Arc::strong_count(&self.inner)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_shared_db_clone_count() {
let _ = std::marker::PhantomData::<SharedDB>;
}
}