find out how to nested the future into handler

This commit is contained in:
appflowy 2021-07-18 23:56:36 +08:00
parent 84931e7cc6
commit e1f73f5246
10 changed files with 114 additions and 80 deletions

View File

@ -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" />

View File

@ -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

View File

@ -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"] }

View File

@ -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| {

View File

@ -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 {

View File

@ -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";

View File

@ -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"] }

View File

@ -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)
}

View File

@ -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>;
}

View File

@ -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)
}