SQLite-backed Key / Value Store
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(wip): working on adding the db store

+84 -14
+6
migrations/20240620173629_create_db.sql
··· 1 + -- Add migration script here 2 + create table if not exists safir ( 3 + key text not null primary key 4 + value text not null 5 + ) 6 + create index if not exists idx_key on safir(key);
+3 -1
src/main.rs
··· 10 10 #[tokio::main] 11 11 async fn main() -> Result<()> { 12 12 let cli = Cli::parse(); 13 - let mut safir = store::init_safir().context("loading safir store")?; 13 + let mut safir = store::init_safir().await.context("loading safir store")?; 14 14 15 15 match cli.command { 16 16 Commands::Add { key, value } => { ··· 24 24 } 25 25 Commands::Alias { keys } => { 26 26 // TODO: Fix custom displays 27 + unimplemented!("alias needs work"); 27 28 // safir.custom_display("alias", keys.to_owned()).await?; 28 29 } 29 30 Commands::Export { keys } => { 31 + unimplemented!("export needs work"); 30 32 // safir.custom_display("export", keys.to_owned()).await?; 31 33 } 32 34 Commands::List => {
+63
src/store/db_store.rs
··· 1 + use anyhow::{Context, Result}; 2 + use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePool, SqlitePoolOptions}; 3 + 4 + use std::path::PathBuf; 5 + use std::str::FromStr; 6 + 7 + use crate::store::SafirStore; 8 + 9 + #[derive(Debug, Clone)] 10 + pub struct SqliteStore { 11 + pool: SqlitePool, 12 + } 13 + 14 + impl SqliteStore { 15 + pub(crate) async fn load(wd: PathBuf) -> Result<Self> { 16 + let lead = PathBuf::from("sqlite:/"); 17 + let db_name = lead.join(wd).join("safirstore.db"); 18 + 19 + let connect_opts = SqliteConnectOptions::from_str(db_name.to_str().unwrap())? 20 + .optimize_on_close(true, None) 21 + .journal_mode(SqliteJournalMode::Wal) 22 + .create_if_missing(true); 23 + 24 + let pool = SqlitePoolOptions::new() 25 + .acquire_timeout(std::time::Duration::from_secs_f64(0.1)) 26 + .connect_with(connect_opts) 27 + .await 28 + .context("creating database")?; 29 + 30 + Self::setup_db(&pool).await?; 31 + Ok(Self { pool }) 32 + } 33 + 34 + async fn setup_db(pool: &SqlitePool) -> Result<()> { 35 + sqlx::migrate!("./migrations") 36 + .run(pool) 37 + .await 38 + .context("running database migrations")?; 39 + 40 + Ok(()) 41 + } 42 + } 43 + 44 + impl SafirStore for SqliteStore { 45 + async fn add(&mut self, key: String, value: String) -> Result<()> { 46 + Ok(()) 47 + } 48 + async fn get(&self, keys: Vec<String>) -> Result<()> { 49 + Ok(()) 50 + } 51 + async fn list(&self) -> Result<()> { 52 + Ok(()) 53 + } 54 + async fn remove(&mut self, keys: Vec<String>) -> Result<()> { 55 + Ok(()) 56 + } 57 + async fn clear(&mut self) -> Result<()> { 58 + Ok(()) 59 + } 60 + async fn purge(&mut self) -> Result<()> { 61 + Ok(()) 62 + } 63 + }
+4 -1
src/store/file_store.rs
··· 18 18 store 19 19 }; 20 20 21 - Self { path: ws, store } 21 + Self { 22 + path: store_path, 23 + store, 24 + } 22 25 } 23 26 24 27 pub fn custom_display(&self, display_cmd: &str, keys: Vec<String>) {
+8 -12
src/store/mod.rs
··· 1 + pub mod db_store; 1 2 pub mod file_store; 2 3 3 4 use crate::utils; 4 5 5 - use std::path::{Path, PathBuf}; 6 + use std::path::Path; 6 7 7 8 use anyhow::{Context, Result}; 8 9 use clap::ValueEnum; 10 + use db_store::SqliteStore; 9 11 use file_store::KVStore; 10 12 use serde::{Deserialize, Serialize}; 11 13 ··· 42 44 } 43 45 } 44 46 45 - pub fn init_safir() -> Result<impl SafirStore> { 46 - // 1. Create .safirstore dir 47 + pub async fn init_safir() -> Result<impl SafirStore> { 47 48 let ws = utils::create_safir_workspace(); 48 - 49 - // 2. Load / Create config 50 49 let cfg = SafirConfig::load(&ws).expect("can't load safir config"); 51 50 52 - // 3. Load / Create stores 53 - let store = match cfg.mode { 54 - SafirMode::File => KVStore::load(ws), 55 - _ => unimplemented!("not yet on db work"), 56 - }; 57 - 58 - Ok(store) 51 + match cfg.mode { 52 + SafirMode::File => Ok(KVStore::load(ws)), 53 + SafirMode::Database => unimplemented!("fix this"), 54 + } 59 55 }