mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
189 lines
4.8 KiB
Rust
189 lines
4.8 KiB
Rust
|
use crate::kv::schema::{kv_table, kv_table::dsl, KV_SQL};
|
||
|
use ::diesel::{query_dsl::*, ExpressionMethods};
|
||
|
use diesel::{Connection, SqliteConnection};
|
||
|
use flowy_derive::ProtoBuf;
|
||
|
use flowy_sqlite::{DBConnection, Database, PoolConfig};
|
||
|
use lazy_static::lazy_static;
|
||
|
use std::{path::Path, sync::RwLock};
|
||
|
const DB_NAME: &str = "kv.db";
|
||
|
lazy_static! {
|
||
|
pub static ref KV_HOLDER: RwLock<KVStore> = RwLock::new(KVStore::new());
|
||
|
}
|
||
|
|
||
|
pub struct KVStore {
|
||
|
database: Option<Database>,
|
||
|
}
|
||
|
|
||
|
impl KVStore {
|
||
|
fn new() -> Self { KVStore { database: None } }
|
||
|
|
||
|
pub fn init(&mut self, root: &str) -> Result<(), String> {
|
||
|
if !Path::new(root).exists() {
|
||
|
return Err(format!("{} not exists", root));
|
||
|
}
|
||
|
|
||
|
let pool_config = PoolConfig::default();
|
||
|
let database = Database::new(root, DB_NAME, pool_config).unwrap();
|
||
|
let conn = database.get_connection().unwrap();
|
||
|
SqliteConnection::execute(&*conn, KV_SQL).unwrap();
|
||
|
self.database = Some(database);
|
||
|
|
||
|
Ok(())
|
||
|
}
|
||
|
|
||
|
pub fn set(item: KeyValue) -> Result<(), String> {
|
||
|
match get_connection() {
|
||
|
Ok(conn) => {
|
||
|
let _ = diesel::insert_into(kv_table::table)
|
||
|
.values(&item)
|
||
|
.execute(&*conn)
|
||
|
.map_err(|e| format!("{:?}", e))?;
|
||
|
|
||
|
Ok(())
|
||
|
},
|
||
|
Err(e) => Err(e),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[allow(dead_code)]
|
||
|
pub fn remove(key: &str) -> Result<(), String> {
|
||
|
match get_connection() {
|
||
|
Ok(conn) => {
|
||
|
let _ = diesel::delete(dsl::kv_table.filter(kv_table::key.eq(key)))
|
||
|
.execute(&*conn)
|
||
|
.map_err(|e| format!("{:?}", e))?;
|
||
|
Ok(())
|
||
|
},
|
||
|
Err(e) => Err(e),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn get(key: &str) -> Result<KeyValue, String> {
|
||
|
match get_connection() {
|
||
|
Ok(conn) => {
|
||
|
let item = dsl::kv_table
|
||
|
.filter(kv_table::key.eq(key))
|
||
|
.first::<KeyValue>(&*conn)
|
||
|
.map_err(|e| format!("{:?}", e))?;
|
||
|
Ok(item)
|
||
|
},
|
||
|
Err(e) => Err(e),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
macro_rules! impl_get_func {
|
||
|
(
|
||
|
$func_name:ident,
|
||
|
$get_method:ident=>$target:ident
|
||
|
) => {
|
||
|
impl KVStore {
|
||
|
#[allow(dead_code)]
|
||
|
pub fn $func_name(k: &str) -> Option<$target> {
|
||
|
match KVStore::get(k) {
|
||
|
Ok(item) => item.$get_method,
|
||
|
Err(_) => None,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
macro_rules! impl_set_func {
|
||
|
($func_name:ident,$set_method:ident,$key_type:ident) => {
|
||
|
impl KVStore {
|
||
|
#[allow(dead_code)]
|
||
|
pub fn $func_name(key: &str, value: $key_type) {
|
||
|
let mut item = KeyValue::new(key);
|
||
|
item.$set_method = Some(value);
|
||
|
match KVStore::set(item) {
|
||
|
Ok(_) => {},
|
||
|
Err(e) => {
|
||
|
log::error!("{:?}", e)
|
||
|
},
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
impl_set_func!(set_str, str_value, String);
|
||
|
|
||
|
impl_set_func!(set_bool, bool_value, bool);
|
||
|
|
||
|
impl_set_func!(set_int, int_value, i64);
|
||
|
|
||
|
impl_set_func!(set_float, float_value, f64);
|
||
|
|
||
|
impl_get_func!(get_str,str_value=>String);
|
||
|
|
||
|
impl_get_func!(get_int,int_value=>i64);
|
||
|
|
||
|
impl_get_func!(get_float,float_value=>f64);
|
||
|
|
||
|
impl_get_func!(get_bool,bool_value=>bool);
|
||
|
|
||
|
fn get_connection() -> Result<DBConnection, String> {
|
||
|
match KV_HOLDER.read() {
|
||
|
Ok(store) => {
|
||
|
let conn = store
|
||
|
.database
|
||
|
.as_ref()
|
||
|
.expect("KVStore is not init")
|
||
|
.get_connection()
|
||
|
.map_err(|e| format!("{:?}", e))?;
|
||
|
Ok(conn)
|
||
|
},
|
||
|
Err(e) => {
|
||
|
let msg = format!("KVStore get connection failed: {:?}", e);
|
||
|
log::error!("{:?}", msg);
|
||
|
Err(msg)
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[derive(
|
||
|
PartialEq, Clone, Debug, ProtoBuf, Default, Queryable, Identifiable, Insertable, AsChangeset,
|
||
|
)]
|
||
|
#[table_name = "kv_table"]
|
||
|
#[primary_key(key)]
|
||
|
pub struct KeyValue {
|
||
|
#[pb(index = 1)]
|
||
|
pub key: String,
|
||
|
|
||
|
#[pb(index = 2, one_of)]
|
||
|
pub str_value: Option<String>,
|
||
|
|
||
|
#[pb(index = 3, one_of)]
|
||
|
pub int_value: Option<i64>,
|
||
|
|
||
|
#[pb(index = 4, one_of)]
|
||
|
pub float_value: Option<f64>,
|
||
|
|
||
|
#[pb(index = 5, one_of)]
|
||
|
pub bool_value: Option<bool>,
|
||
|
}
|
||
|
|
||
|
impl KeyValue {
|
||
|
pub fn new(key: &str) -> Self {
|
||
|
KeyValue {
|
||
|
key: key.to_string(),
|
||
|
..Default::default()
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[derive(ProtoBuf, Default, Debug)]
|
||
|
pub struct KeyValueQuery {
|
||
|
#[pb(index = 1)]
|
||
|
key: String,
|
||
|
}
|
||
|
|
||
|
impl KeyValueQuery {
|
||
|
pub fn new(key: &str) -> Self {
|
||
|
let mut query = KeyValueQuery::default();
|
||
|
query.key = key.to_string();
|
||
|
query
|
||
|
}
|
||
|
}
|