use crate::constants::{APP_DB_DATA_DIR, DB_COLUMNS}; use rocksdb::{ColumnFamilyDescriptor, IteratorMode, OptimisticTransactionDB, Options, ReadOptions}; use serde::{Serialize}; use serde::de::DeserializeOwned; use crate::models::RocksColumn; pub struct RocksDB { db: OptimisticTransactionDB, } impl RocksDB { pub fn new(db_opts: Options, cf_opts: Options) -> color_eyre::Result { let cfs = DB_COLUMNS.iter() .map(|cf| ColumnFamilyDescriptor::new(cf.to_string(), cf_opts.clone())) .collect::>(); let db = OptimisticTransactionDB::open_cf_descriptors( &db_opts, APP_DB_DATA_DIR.as_path(), cfs )?; let rocks = Self { db }; Ok(rocks) } pub fn get_value(&self, id: TColumn::Id) -> color_eyre::Result> where TColumn: RocksColumn, TValue: DeserializeOwned { let cf = self.db.cf_handle(TColumn::get_column_name().as_str()).unwrap(); let query_res = self.db.get_cf(&cf, serde_json::to_string(&id)?)?; if query_res.is_none() { return Ok(None); } Ok(Some(serde_json::from_slice(&query_res.unwrap())?)) } pub fn set_value(&self, value: &TColumn) -> color_eyre::Result<()> where TColumn: RocksColumn + Serialize { let cf = self.db.cf_handle(TColumn::get_column_name().as_str()).unwrap(); self.db.put_cf(&cf, serde_json::to_string(&value.get_id())?, serde_json::to_string(value)?)?; Ok(()) } pub fn get_values(&self, ids: &[TColumn::Id]) -> color_eyre::Result> where TColumn: RocksColumn + DeserializeOwned { let transaction = self.db.transaction(); let cf = self.db.cf_handle(TColumn::get_column_name().as_str()).unwrap(); let mut values = Vec::new(); for id in ids { let query_res = transaction.get_cf(&cf, serde_json::to_string(id)?)?; if let Some(res) = query_res { let value = serde_json::from_slice(&res)?; values.push(value); } } Ok(values) } pub fn get_all_values(&self) -> color_eyre::Result> where TColumn: RocksColumn + DeserializeOwned { let cf = self.db.cf_handle(TColumn::get_column_name().as_str()).unwrap(); let mut options = ReadOptions::default(); options.set_async_io(true); let values = self.db.iterator_cf_opt(&cf, options, IteratorMode::Start) .filter_map(Result::ok) .map(|(k, v)| ( serde_json::from_slice::(&k).unwrap(), serde_json::from_slice::(&v).unwrap() ) ) .collect::>(); Ok(values) } pub fn set_values(&self, values: &[TColumn]) -> color_eyre::Result<()> where TColumn: RocksColumn + Serialize { let transaction = self.db.transaction(); let cf = self.db.cf_handle(TColumn::get_column_name().as_str()).unwrap(); for value in values { transaction.put_cf(&cf, serde_json::to_string(&value.get_id())?, serde_json::to_string(value)?)?; } transaction.commit()?; Ok(()) } }