From e1f73f5246a353f03527a4b37a76f1d9b258adef Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 18 Jul 2021 23:56:36 +0800 Subject: [PATCH] find out how to nested the future into handler --- .idea/appflowy_client.iml | 3 + app_flowy/macos/Podfile.lock | 6 + rust-lib/flowy-sdk/Cargo.toml | 1 + rust-lib/flowy-sdk/src/module.rs | 22 +++- .../src/services/user_session/database.rs | 21 ++-- .../src/services/user_session/user_session.rs | 106 ++++++++---------- rust-lib/flowy-workspace/Cargo.toml | 2 + .../src/handlers/workspace_handler.rs | 9 +- rust-lib/flowy-workspace/src/module.rs | 3 +- .../src/services/workspace_controller.rs | 21 +++- 10 files changed, 114 insertions(+), 80 deletions(-) diff --git a/.idea/appflowy_client.iml b/.idea/appflowy_client.iml index 5c6b5b4d21..fbd3a47727 100644 --- a/.idea/appflowy_client.iml +++ b/.idea/appflowy_client.iml @@ -86,6 +86,9 @@ + + + diff --git a/app_flowy/macos/Podfile.lock b/app_flowy/macos/Podfile.lock index 8aca69f25a..54e66df1b4 100644 --- a/app_flowy/macos/Podfile.lock +++ b/app_flowy/macos/Podfile.lock @@ -1,6 +1,8 @@ PODS: - flowy_editor (0.0.1): - FlutterMacOS + - flowy_infra_ui (0.0.1): + - FlutterMacOS - flowy_sdk (0.0.1): - FlutterMacOS - FlutterMacOS (1.0.0) @@ -13,6 +15,7 @@ PODS: DEPENDENCIES: - flowy_editor (from `Flutter/ephemeral/.symlinks/plugins/flowy_editor/macos`) + - flowy_infra_ui (from `Flutter/ephemeral/.symlinks/plugins/flowy_infra_ui/macos`) - flowy_sdk (from `Flutter/ephemeral/.symlinks/plugins/flowy_sdk/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`) @@ -22,6 +25,8 @@ DEPENDENCIES: EXTERNAL SOURCES: flowy_editor: :path: Flutter/ephemeral/.symlinks/plugins/flowy_editor/macos + flowy_infra_ui: + :path: Flutter/ephemeral/.symlinks/plugins/flowy_infra_ui/macos flowy_sdk: :path: Flutter/ephemeral/.symlinks/plugins/flowy_sdk/macos FlutterMacOS: @@ -35,6 +40,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: flowy_editor: 26060a984848e6afac1f6a4455511f4114119d8d + flowy_infra_ui: 9d5021b1610fe0476eb1191bf7cd41c4a4138d8f flowy_sdk: c302ac0a22dea596db0df8073b9637b2bf2ff6fd FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424 path_provider_macos: a0a3fd666cb7cd0448e936fb4abad4052961002b diff --git a/rust-lib/flowy-sdk/Cargo.toml b/rust-lib/flowy-sdk/Cargo.toml index 9be05f9cf8..6150dd01a3 100644 --- a/rust-lib/flowy-sdk/Cargo.toml +++ b/rust-lib/flowy-sdk/Cargo.toml @@ -15,6 +15,7 @@ flowy-workspace = { path = "../flowy-workspace" } flowy-database = { path = "../flowy-database" } tracing = { version = "0.1" } log = "0.4.14" +futures-core = { version = "0.3", default-features = false } [dev-dependencies] serde = { version = "1.0", features = ["derive"] } diff --git a/rust-lib/flowy-sdk/src/module.rs b/rust-lib/flowy-sdk/src/module.rs index ed0afda2f2..b13c3e336a 100644 --- a/rust-lib/flowy-sdk/src/module.rs +++ b/rust-lib/flowy-sdk/src/module.rs @@ -1,11 +1,10 @@ -use flowy_dispatch::prelude::Module; -use flowy_user::prelude::*; - use crate::flowy_server::{ArcFlowyServer, FlowyServerMocker}; use flowy_database::DBConnection; - +use flowy_dispatch::prelude::Module; +use flowy_user::{errors::UserError, prelude::*}; use flowy_workspace::prelude::*; -use std::sync::Arc; +use futures_core::future::BoxFuture; +use std::{pin::Pin, sync::Arc}; pub struct ModuleConfig { pub root: String, @@ -33,7 +32,18 @@ pub struct WorkspaceUserImpl { } impl WorkspaceUser for WorkspaceUserImpl { - fn set_current_workspace(&self, id: &str) { UserSession::set_current_workspace(id); } + fn set_current_workspace(&self, workspace_id: &str) -> BoxFuture<()> { + let user_session = self.user_session.clone(); + let workspace_id = workspace_id.to_owned(); + Box::pin(async move { + match user_session.set_current_workspace(&workspace_id).await { + Ok(_) => {}, + Err(e) => { + log::error!("Set current workspace error: {:?}", e); + }, + } + }) + } fn get_current_workspace(&self) -> Result { let user_detail = self.user_session.user_detail().map_err(|e| { diff --git a/rust-lib/flowy-user/src/services/user_session/database.rs b/rust-lib/flowy-user/src/services/user_session/database.rs index 77b621c6d5..6103ec4e1c 100644 --- a/rust-lib/flowy-user/src/services/user_session/database.rs +++ b/rust-lib/flowy-user/src/services/user_session/database.rs @@ -28,7 +28,11 @@ impl UserDB { } fn open_user_db(&self, user_id: &str) -> Result<(), UserError> { - set_user_db_init(true, user_id); + if user_id.is_empty() { + return Err(ErrorBuilder::new(UserErrorCode::DatabaseInitFailed) + .msg("user id is empty") + .build()); + } let dir = format!("{}/{}", self.db_dir, user_id); let db = flowy_database::init(&dir).map_err(|e| { @@ -48,21 +52,20 @@ impl UserDB { } pub(crate) fn close_user_db(&self, user_id: &str) -> Result<(), UserError> { - set_user_db_init(false, user_id); - let mut db_map = DB_MAP.write().map_err(|e| { ErrorBuilder::new(UserErrorCode::DatabaseWriteLocked) .msg(format!("Close user db failed. {:?}", e)) .build() })?; - + set_user_db_init(false, user_id); db_map.remove(user_id); Ok(()) } pub(crate) fn get_connection(&self, user_id: &str) -> Result { if !is_user_db_init(user_id) { - let _ = self.open_user_db(user_id); + let _ = self.open_user_db(user_id)?; + set_user_db_init(true, user_id); } let db_map = DB_MAP.read().map_err(|e| { @@ -73,7 +76,7 @@ impl UserDB { match db_map.get(user_id) { None => Err(ErrorBuilder::new(UserErrorCode::DatabaseInitFailed) - .msg("Database is not initialization") + .msg("Get connection failed. The database is not initialization") .build()), Some(database) => Ok(database.get_connection()?), } @@ -86,10 +89,8 @@ lazy_static! { static INIT_FLAG_MAP: Lazy>> = 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); + let mut flag_map = INIT_FLAG_MAP.lock(); + flag_map.insert(user_id.to_owned(), is_init); } fn is_user_db_init(user_id: &str) -> bool { diff --git a/rust-lib/flowy-user/src/services/user_session/user_session.rs b/rust-lib/flowy-user/src/services/user_session/user_session.rs index 07b4898f8a..18f4621e59 100644 --- a/rust-lib/flowy-user/src/services/user_session/user_session.rs +++ b/rust-lib/flowy-user/src/services/user_session/user_session.rs @@ -34,6 +34,7 @@ pub struct UserSession { database: UserDB, config: UserSessionConfig, server: Arc, + user_id: RwLock>, } impl UserSession { @@ -46,28 +47,30 @@ impl UserSession { database: db, config, server, + user_id: RwLock::new(None), } } pub fn get_db_connection(&self) -> Result { - let user_id = get_current_user_id()?; + let user_id = self.get_user_id()?; self.database.get_connection(&user_id) } pub fn sign_in(&self, params: SignInParams) -> Result { let user = self.server.sign_in(params)?; - let _ = set_current_user_id(Some(user.id.clone()))?; + let _ = self.set_user_id(Some(user.id.clone()))?; + self.save_user(user) } pub fn sign_up(&self, params: SignUpParams) -> Result { let user = self.server.sign_up(params)?; - let _ = set_current_user_id(Some(user.id.clone()))?; + let _ = self.set_user_id(Some(user.id.clone()))?; self.save_user(user) } pub fn sign_out(&self) -> Result<(), UserError> { - let user_id = current_user_id()?; + let user_id = self.get_user_id()?; let conn = self.get_db_connection()?; let _ = diesel::delete(dsl::user_table.filter(dsl::id.eq(&user_id))).execute(&*conn)?; @@ -76,7 +79,7 @@ impl UserSession { Err(_) => {}, } let _ = self.database.close_user_db(&user_id)?; - let _ = set_current_user_id(None)?; + let _ = self.set_user_id(None)?; Ok(()) } @@ -100,7 +103,7 @@ impl UserSession { } pub fn user_detail(&self) -> Result { - let user_id = current_user_id()?; + let user_id = self.get_user_id()?; let conn = self.get_db_connection()?; let user = dsl::user_table @@ -118,16 +121,49 @@ impl UserSession { Ok(UserDetail::from(user)) } -} -impl UserSession { - pub async fn set_current_workspace(workspace: &str) -> Result<(), UserError> { - let user_id = current_user_id()?; + pub fn set_user_id(&self, user_id: Option) -> Result<(), UserError> { + log::trace!("Set user id: {:?}", user_id); + KVStore::set_str(USER_ID_CACHE_KEY, user_id.clone().unwrap_or("".to_owned())); + match self.user_id.write() { + Ok(mut write_guard) => { + *write_guard = user_id; + Ok(()) + }, + Err(e) => Err(ErrorBuilder::new(UserErrorCode::WriteCurrentIdFailed) + .error(e) + .build()), + } + } + + pub fn get_user_id(&self) -> Result { + let read_guard = self.user_id.read().map_err(|e| { + ErrorBuilder::new(UserErrorCode::ReadCurrentIdFailed) + .error(e) + .build() + })?; + + let mut user_id = (*read_guard).clone(); + drop(read_guard); + + if user_id.is_none() { + user_id = KVStore::get_str(USER_ID_CACHE_KEY); + self.set_user_id(user_id.clone()); + } + + match user_id { + None => Err(ErrorBuilder::new(UserErrorCode::UserNotLoginYet).build()), + Some(user_id) => Ok(user_id), + } + } + + pub async fn set_current_workspace(&self, workspace_id: &str) -> Result<(), UserError> { + let user_id = self.get_user_id()?; let payload: Vec = UpdateUserRequest { id: user_id, name: None, email: None, - workspace: Some(workspace.to_owned()), + workspace: Some(workspace_id.to_owned()), password: None, } .into_bytes() @@ -144,7 +180,7 @@ impl UserSession { } pub fn current_user_id() -> Result { - match KVStore::get_str(USER_ID_DISK_CACHE_KEY) { + match KVStore::get_str(USER_ID_CACHE_KEY) { None => Err(ErrorBuilder::new(UserErrorCode::UserNotLoginYet).build()), Some(user_id) => Ok(user_id), } @@ -156,48 +192,4 @@ impl UserDatabaseConnection for UserSession { } } -const USER_ID_DISK_CACHE_KEY: &str = "user_id"; -lazy_static! { - pub static ref CURRENT_USER_ID: RwLock> = RwLock::new(None); -} - -pub(crate) fn get_current_user_id() -> Result { - let read_guard = CURRENT_USER_ID.read().map_err(|e| { - ErrorBuilder::new(UserErrorCode::ReadCurrentIdFailed) - .error(e) - .build() - })?; - - let mut user_id = (*read_guard).clone(); - // explicitly drop the read_guard in case of dead lock - drop(read_guard); - - if user_id.is_none() { - user_id = KVStore::get_str(USER_ID_DISK_CACHE_KEY); - *(CURRENT_USER_ID.write().unwrap()) = user_id.clone(); - } - - if user_id.is_none() { - return Err(ErrorBuilder::new(UserErrorCode::UserNotLoginYet).build()); - } - - match user_id { - None => Err(ErrorBuilder::new(UserErrorCode::UserNotLoginYet).build()), - Some(user_id) => Ok(user_id), - } -} - -pub(crate) fn set_current_user_id(user_id: Option) -> Result<(), UserError> { - KVStore::set_str( - USER_ID_DISK_CACHE_KEY, - user_id.clone().unwrap_or("".to_owned()), - ); - - let mut current_user_id = CURRENT_USER_ID.write().map_err(|e| { - ErrorBuilder::new(UserErrorCode::WriteCurrentIdFailed) - .error(e) - .build() - })?; - *current_user_id = user_id; - Ok(()) -} +const USER_ID_CACHE_KEY: &str = "user_id"; diff --git a/rust-lib/flowy-workspace/Cargo.toml b/rust-lib/flowy-workspace/Cargo.toml index 4610dcdcf7..3ec792721b 100644 --- a/rust-lib/flowy-workspace/Cargo.toml +++ b/rust-lib/flowy-workspace/Cargo.toml @@ -16,6 +16,8 @@ protobuf = {version = "2.18.0"} log = "0.4.14" diesel = {version = "1.4.7", features = ["sqlite"]} diesel_derives = {version = "1.4.1", features = ["sqlite"]} +futures-core = { version = "0.3", default-features = false } +pin-project = "1.0.0" lazy_static = "1.4.0" serde = { version = "1.0", features = ["derive"] } diff --git a/rust-lib/flowy-workspace/src/handlers/workspace_handler.rs b/rust-lib/flowy-workspace/src/handlers/workspace_handler.rs index 4faf654c21..1f519190a2 100644 --- a/rust-lib/flowy-workspace/src/handlers/workspace_handler.rs +++ b/rust-lib/flowy-workspace/src/handlers/workspace_handler.rs @@ -1,16 +1,17 @@ use crate::{ entities::workspace::{CreateWorkspaceParams, CreateWorkspaceRequest, WorkspaceDetail}, errors::WorkspaceError, - services::WorkspaceController, + services::{save_workspace, WorkspaceController}, }; -use flowy_dispatch::prelude::{response_ok, Data, ModuleData, ResponseResult}; -use std::{convert::TryInto, sync::Arc}; +use flowy_dispatch::prelude::{response_ok, Data, EventResponse, ModuleData, ResponseResult}; +use std::{convert::TryInto, pin::Pin, sync::Arc}; pub async fn create_workspace( data: Data, controller: ModuleData>, ) -> ResponseResult { + let controller = controller.get_ref().clone(); let params: CreateWorkspaceParams = data.into_inner().try_into()?; - let detail = controller.save_workspace(params)?; + let detail = save_workspace(controller, params).await?; response_ok(detail) } diff --git a/rust-lib/flowy-workspace/src/module.rs b/rust-lib/flowy-workspace/src/module.rs index 4dc6f0bfdd..9d1e67fec8 100644 --- a/rust-lib/flowy-workspace/src/module.rs +++ b/rust-lib/flowy-workspace/src/module.rs @@ -7,10 +7,11 @@ use crate::{ services::{AppController, WorkspaceController}, }; use flowy_database::DBConnection; +use futures_core::future::BoxFuture; use std::sync::Arc; pub trait WorkspaceUser: Send + Sync { - fn set_current_workspace(&self, id: &str); + fn set_current_workspace(&self, id: &str) -> BoxFuture<()>; fn get_current_workspace(&self) -> Result; fn db_connection(&self) -> Result; } diff --git a/rust-lib/flowy-workspace/src/services/workspace_controller.rs b/rust-lib/flowy-workspace/src/services/workspace_controller.rs index 568cdc06bd..28b7b0af7a 100644 --- a/rust-lib/flowy-workspace/src/services/workspace_controller.rs +++ b/rust-lib/flowy-workspace/src/services/workspace_controller.rs @@ -1,15 +1,16 @@ use crate::{entities::workspace::*, errors::*, module::WorkspaceUser, sql_tables::workspace::*}; use flowy_database::{prelude::*, schema::workspace_table}; +use futures_core::future::BoxFuture; use std::sync::Arc; pub struct WorkspaceController { - pub(crate) user: Arc, + pub user: Arc, } impl WorkspaceController { pub fn new(user: Arc) -> Self { Self { user } } - pub fn save_workspace( + pub async fn save_workspace( &self, params: CreateWorkspaceParams, ) -> Result { @@ -34,3 +35,19 @@ impl WorkspaceController { Ok(()) } } + +pub async fn save_workspace( + controller: Arc, + params: CreateWorkspaceParams, +) -> Result { + let workspace = Workspace::new(params); + let detail: WorkspaceDetail = workspace.clone().into(); + + let _ = diesel::insert_into(workspace_table::table) + .values(workspace) + .execute(&*(controller.user.db_connection()?))?; + + // set_current_workspace(controller.clone(), &detail.id).await; + + Ok(detail) +}