AppFlowy/rust-lib/flowy-user/src/services/user_session/database.rs

110 lines
2.8 KiB
Rust
Raw Normal View History

use crate::errors::{ErrorBuilder, UserError, UserErrorCode};
use flowy_database::{DBConnection, Database};
2021-07-09 15:31:44 +00:00
use lazy_static::lazy_static;
2021-07-18 01:03:21 +00:00
use once_cell::sync::Lazy;
use parking_lot::Mutex;
2021-07-09 15:31:44 +00:00
use std::{
cell::RefCell,
2021-07-18 01:03:21 +00:00
collections::HashMap,
2021-07-09 15:31:44 +00:00
sync::{
atomic::{AtomicBool, Ordering},
RwLock,
},
};
lazy_static! {
static ref DB: RwLock<Option<Database>> = RwLock::new(None);
2021-07-09 15:31:44 +00:00
}
pub(crate) struct UserDB {
db_dir: String,
}
impl UserDB {
pub(crate) fn new(db_dir: &str) -> Self {
Self {
db_dir: db_dir.to_owned(),
}
}
fn open_user_db(&self, user_id: &str) -> Result<(), UserError> {
2021-07-18 01:03:21 +00:00
set_user_db_init(true, user_id);
let dir = format!("{}/{}", self.db_dir, user_id);
let db = flowy_database::init(&dir).map_err(|e| {
ErrorBuilder::new(UserErrorCode::DatabaseInitFailed)
.error(e)
.build()
})?;
2021-07-18 01:03:21 +00:00
let mut db_map = DB_MAP.write().map_err(|e| {
ErrorBuilder::new(UserErrorCode::DatabaseWriteLocked)
.error(e)
.build()
})?;
2021-07-18 01:03:21 +00:00
db_map.insert(user_id.to_owned(), db);
2021-07-09 15:31:44 +00:00
Ok(())
}
2021-07-18 01:03:21 +00:00
pub(crate) fn close_user_db(&self, user_id: &str) -> Result<(), UserError> {
set_user_db_init(false, user_id);
2021-07-18 01:03:21 +00:00
let mut db_map = DB_MAP.write().map_err(|e| {
ErrorBuilder::new(UserErrorCode::DatabaseWriteLocked)
.msg(format!("Close user db failed. {:?}", e))
.build()
})?;
2021-07-18 01:03:21 +00:00
db_map.remove(user_id);
2021-07-09 15:31:44 +00:00
Ok(())
}
pub(crate) fn get_connection(&self, user_id: &str) -> Result<DBConnection, UserError> {
2021-07-18 01:03:21 +00:00
if !is_user_db_init(user_id) {
2021-07-09 15:31:44 +00:00
let _ = self.open_user_db(user_id);
}
2021-07-18 01:03:21 +00:00
let db_map = DB_MAP.read().map_err(|e| {
ErrorBuilder::new(UserErrorCode::DatabaseReadLocked)
.error(e)
.build()
})?;
2021-07-18 01:03:21 +00:00
match db_map.get(user_id) {
None => Err(ErrorBuilder::new(UserErrorCode::DatabaseInitFailed)
.msg("Database is not initialization")
.build()),
2021-07-09 15:31:44 +00:00
Some(database) => Ok(database.get_connection()?),
}
}
}
2021-07-18 01:03:21 +00:00
lazy_static! {
static ref DB_MAP: RwLock<HashMap<String, Database>> = RwLock::new(HashMap::new());
}
2021-07-18 01:03:21 +00:00
static INIT_FLAG_MAP: Lazy<Mutex<HashMap<String, bool>>> = Lazy::new(|| Mutex::new(HashMap::new()));
fn set_user_db_init(is_init: bool, user_id: &str) {
INIT_FLAG_MAP
.lock()
.entry(user_id.to_owned())
.or_insert_with(|| is_init);
}
2021-07-18 01:03:21 +00:00
fn is_user_db_init(user_id: &str) -> bool {
match INIT_FLAG_MAP.lock().get(user_id) {
None => false,
Some(flag) => flag.clone(),
}
}
2021-07-09 15:31:44 +00:00
#[cfg(test)]
mod tests {
2021-07-09 15:31:44 +00:00
#[test]
fn init_db_test() {
// init_user_db(".").unwrap();
}
}