kanban-persistence-sqlite 0.5.1

SQLite storage backend for the kanban project management tool
Documentation
pub mod sqlite_store;

pub use sqlite_store::SqliteStore;

use kanban_persistence::{PersistenceError, PersistenceStore, StoreFactory};
use std::sync::Arc;

pub struct SqliteStoreFactory;

impl StoreFactory for SqliteStoreFactory {
    fn name(&self) -> &str {
        "sqlite"
    }

    fn matches_content(&self, header: &[u8]) -> bool {
        header.starts_with(b"SQLite format 3\0")
    }

    fn create(
        &self,
        locator: &str,
    ) -> Result<Arc<dyn PersistenceStore + Send + Sync>, PersistenceError> {
        let handle = tokio::runtime::Handle::current();
        if handle.runtime_flavor() == tokio::runtime::RuntimeFlavor::CurrentThread {
            return Err(PersistenceError::Database(
                "SqliteStoreFactory::create requires a multi-thread Tokio runtime; \
                 block_in_place is unavailable on a current_thread runtime. \
                 Use #[tokio::test(flavor = \"multi_thread\")] in tests."
                    .to_string(),
            ));
        }
        let store = tokio::task::block_in_place(|| handle.block_on(SqliteStore::open(locator)))
            .map_err(|e| PersistenceError::Database(e.to_string()))?;
        Ok(Arc::new(store))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use kanban_persistence::StoreFactory;

    #[test]
    fn test_sqlite_factory_matches_content_sqlite_magic_bytes() {
        let header = b"SQLite format 3\0extra";
        assert!(SqliteStoreFactory.matches_content(header));
    }

    #[test]
    fn test_sqlite_factory_matches_content_rejects_json() {
        let header = b"{\"boards\": []}";
        assert!(!SqliteStoreFactory.matches_content(header));
    }

    #[test]
    fn test_sqlite_factory_matches_content_rejects_empty() {
        assert!(!SqliteStoreFactory.matches_content(b""));
    }

    #[test]
    fn test_sqlite_factory_name_is_sqlite() {
        assert_eq!(SqliteStoreFactory.name(), "sqlite");
    }

    #[tokio::test(flavor = "multi_thread")]
    async fn test_sqlite_factory_create_returns_persistence_store() {
        let dir = tempfile::tempdir().unwrap();
        let path = dir.path().join("test.db");
        let store = SqliteStoreFactory.create(path.to_str().unwrap()).unwrap();
        assert!(store.exists().await);
    }
}