Browse Source

find out how to nested the future into handler

appflowy 3 years ago
parent
commit
e1f73f5246

+ 3 - 0
.idea/appflowy_client.iml

@@ -86,6 +86,9 @@
       <excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/flowy_infra_ui/.pub" />
       <excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/flowy_infra_ui/.dart_tool" />
       <excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/flowy_infra_ui/build" />
+      <excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/flowy_infra_ui/example/.dart_tool" />
+      <excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/flowy_infra_ui/example/build" />
+      <excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/flowy_infra_ui/example/.pub" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />

+ 6 - 0
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

+ 1 - 0
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"] }

+ 16 - 6
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<String, WorkspaceError> {
         let user_detail = self.user_session.user_detail().map_err(|e| {

+ 11 - 10
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<DBConnection, UserError> {
         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<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);
+    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 {

+ 49 - 57
rust-lib/flowy-user/src/services/user_session/user_session.rs

@@ -34,6 +34,7 @@ pub struct UserSession {
     database: UserDB,
     config: UserSessionConfig,
     server: Arc<dyn UserServer + Send + Sync>,
+    user_id: RwLock<Option<String>>,
 }
 
 impl UserSession {
@@ -46,28 +47,30 @@ impl UserSession {
             database: db,
             config,
             server,
+            user_id: RwLock::new(None),
         }
     }
 
     pub fn get_db_connection(&self) -> Result<DBConnection, UserError> {
-        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<User, UserError> {
         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<User, UserError> {
         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<UserDetail, UserError> {
-        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<String>) -> 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<String, UserError> {
+        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<u8> = 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<String, UserError> {
-    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<Option<String>> = RwLock::new(None);
-}
-
-pub(crate) fn get_current_user_id() -> Result<String, UserError> {
-    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<String>) -> 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";

+ 2 - 0
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"] }

+ 5 - 4
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<CreateWorkspaceRequest>,
     controller: ModuleData<Arc<WorkspaceController>>,
 ) -> ResponseResult<WorkspaceDetail, WorkspaceError> {
+    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)
 }

+ 2 - 1
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<String, WorkspaceError>;
     fn db_connection(&self) -> Result<DBConnection, WorkspaceError>;
 }

+ 19 - 2
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<dyn WorkspaceUser>,
+    pub user: Arc<dyn WorkspaceUser>,
 }
 
 impl WorkspaceController {
     pub fn new(user: Arc<dyn WorkspaceUser>) -> Self { Self { user } }
 
-    pub fn save_workspace(
+    pub async fn save_workspace(
         &self,
         params: CreateWorkspaceParams,
     ) -> Result<WorkspaceDetail, WorkspaceError> {
@@ -34,3 +35,19 @@ impl WorkspaceController {
         Ok(())
     }
 }
+
+pub async fn save_workspace(
+    controller: Arc<WorkspaceController>,
+    params: CreateWorkspaceParams,
+) -> Result<WorkspaceDetail, WorkspaceError> {
+    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)
+}