Selaa lähdekoodia

support multi user db initialize

appflowy 3 vuotta sitten
vanhempi
commit
a63d5f5eaf

+ 4 - 0
rust-lib/flowy-user/Cargo.toml

@@ -26,6 +26,10 @@ lazy_static = "1.4.0"
 fancy-regex = "0.5.0"
 diesel = {version = "1.4.7", features = ["sqlite"]}
 diesel_derives = {version = "1.4.1", features = ["sqlite"]}
+thread_local = "1.1.3"
+thread-id = "3.3.0"
+once_cell = "1.7.2"
+parking_lot = "0.11"
 
 [dev-dependencies]
 quickcheck = "0.9.2"

+ 30 - 36
rust-lib/flowy-user/src/services/user_session/database.rs

@@ -1,8 +1,11 @@
 use crate::errors::{ErrorBuilder, UserError, UserErrorCode};
 use flowy_database::{DBConnection, Database};
 use lazy_static::lazy_static;
+use once_cell::sync::Lazy;
+use parking_lot::Mutex;
 use std::{
     cell::RefCell,
+    collections::HashMap,
     sync::{
         atomic::{AtomicBool, Ordering},
         RwLock,
@@ -25,7 +28,8 @@ impl UserDB {
     }
 
     fn open_user_db(&self, user_id: &str) -> Result<(), UserError> {
-        INIT_FLAG.store(true, Ordering::SeqCst);
+        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)
@@ -33,58 +37,41 @@ impl UserDB {
                 .build()
         })?;
 
-        let mut user_db = DB.write().map_err(|e| {
+        let mut db_map = DB_MAP.write().map_err(|e| {
             ErrorBuilder::new(UserErrorCode::DatabaseWriteLocked)
                 .error(e)
                 .build()
         })?;
-        *(user_db) = Some(db);
 
-        set_user_id(Some(user_id.to_owned()));
+        db_map.insert(user_id.to_owned(), db);
         Ok(())
     }
 
-    pub(crate) fn close_user_db(&self) -> Result<(), UserError> {
-        INIT_FLAG.store(false, Ordering::SeqCst);
+    pub(crate) fn close_user_db(&self, user_id: &str) -> Result<(), UserError> {
+        set_user_db_init(false, user_id);
 
-        let mut write_guard = DB.write().map_err(|e| {
+        let mut db_map = DB_MAP.write().map_err(|e| {
             ErrorBuilder::new(UserErrorCode::DatabaseWriteLocked)
                 .msg(format!("Close user db failed. {:?}", e))
                 .build()
         })?;
 
-        *write_guard = None;
-        set_user_id(None);
-
+        db_map.remove(user_id);
         Ok(())
     }
 
     pub(crate) fn get_connection(&self, user_id: &str) -> Result<DBConnection, UserError> {
-        if !INIT_FLAG.load(Ordering::SeqCst) {
+        if !is_user_db_init(user_id) {
             let _ = self.open_user_db(user_id);
         }
 
-        let thread_user_id = get_user_id();
-        if thread_user_id.is_some() {
-            if thread_user_id != Some(user_id.to_owned()) {
-                let msg = format!(
-                    "Database owner does not match. origin: {:?}, current: {}",
-                    thread_user_id, user_id
-                );
-                log::error!("{}", msg);
-
-                return Err(ErrorBuilder::new(UserErrorCode::DatabaseUserDidNotMatch)
-                    .msg(msg)
-                    .build());
-            }
-        }
-
-        let read_guard = DB.read().map_err(|e| {
+        let db_map = DB_MAP.read().map_err(|e| {
             ErrorBuilder::new(UserErrorCode::DatabaseReadLocked)
                 .error(e)
                 .build()
         })?;
-        match read_guard.as_ref() {
+
+        match db_map.get(user_id) {
             None => Err(ErrorBuilder::new(UserErrorCode::DatabaseInitFailed)
                 .msg("Database is not initialization")
                 .build()),
@@ -93,17 +80,24 @@ impl UserDB {
     }
 }
 
-thread_local! {
-    static USER_ID: RefCell<Option<String>> = RefCell::new(None);
+lazy_static! {
+    static ref DB_MAP: RwLock<HashMap<String, Database>> = RwLock::new(HashMap::new());
 }
-fn set_user_id(user_id: Option<String>) {
-    USER_ID.with(|id| {
-        *id.borrow_mut() = user_id;
-    });
+
+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);
 }
-fn get_user_id() -> Option<String> { USER_ID.with(|id| id.borrow().clone()) }
 
-static INIT_FLAG: AtomicBool = AtomicBool::new(false);
+fn is_user_db_init(user_id: &str) -> bool {
+    match INIT_FLAG_MAP.lock().get(user_id) {
+        None => false,
+        Some(flag) => flag.clone(),
+    }
+}
 
 #[cfg(test)]
 mod tests {

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

@@ -75,7 +75,7 @@ impl UserSession {
             Ok(_) => {},
             Err(_) => {},
         }
-        let _ = self.database.close_user_db()?;
+        let _ = self.database.close_user_db(&user_id)?;
         let _ = set_current_user_id(None)?;
 
         Ok(())

+ 232 - 0
rust-lib/flowy-user/tests/event/sign_in_test.rs

@@ -20,6 +20,7 @@ fn sign_in_success() {
 }
 
 #[test]
+#[serial]
 fn sign_in_with_invalid_email() {
     for email in invalid_email_test_case() {
         let request = SignInRequest {
@@ -40,6 +41,7 @@ fn sign_in_with_invalid_email() {
 }
 
 #[test]
+#[serial]
 fn sign_in_with_invalid_password() {
     for password in invalid_password_test_case() {
         let request = SignInRequest {
@@ -58,3 +60,233 @@ fn sign_in_with_invalid_password() {
         );
     }
 }
+
+#[test]
+#[serial]
+fn sign_up_success() {
+    let _ = UserTestBuilder::new().event(SignOut).sync_send();
+    let request = SignUpRequest {
+        email: random_valid_email(),
+        name: valid_name(),
+        password: valid_password(),
+    };
+
+    let _response = UserTestBuilder::new()
+        .logout()
+        .event(SignUp)
+        .request(request)
+        .sync_send();
+}
+
+#[test]
+#[serial]
+fn sign_up_with_invalid_email() {
+    for email in invalid_email_test_case() {
+        let request = SignUpRequest {
+            email: email.to_string(),
+            name: valid_name(),
+            password: valid_password(),
+        };
+
+        assert_eq!(
+            UserTestBuilder::new()
+                .event(SignUp)
+                .request(request)
+                .sync_send()
+                .error()
+                .code,
+            UserErrorCode::EmailInvalid
+        );
+    }
+}
+#[test]
+#[serial]
+fn sign_up_with_invalid_password() {
+    for password in invalid_password_test_case() {
+        let request = SignUpRequest {
+            email: random_valid_email(),
+            name: valid_name(),
+            password,
+        };
+
+        assert_eq!(
+            UserTestBuilder::new()
+                .event(SignUp)
+                .request(request)
+                .sync_send()
+                .error()
+                .code,
+            UserErrorCode::PasswordInvalid
+        );
+    }
+}
+
+#[test]
+#[should_panic]
+#[serial]
+fn user_status_get_failed_before_login() {
+    let _ = UserTestBuilder::new()
+        .logout()
+        .event(GetStatus)
+        .sync_send()
+        .parse::<UserDetail>();
+}
+
+#[test]
+#[serial]
+fn user_status_get_success_after_login() {
+    let request = SignInRequest {
+        email: random_valid_email(),
+        password: valid_password(),
+    };
+
+    let response = UserTestBuilder::new()
+        .logout()
+        .event(SignIn)
+        .request(request)
+        .sync_send()
+        .parse::<UserDetail>();
+    dbg!(&response);
+
+    let _ = UserTestBuilder::new()
+        .event(GetStatus)
+        .sync_send()
+        .parse::<UserDetail>();
+}
+
+#[test]
+#[serial]
+fn user_update_with_name() {
+    let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
+    let new_name = "hello_world".to_owned();
+    let request = UpdateUserRequest {
+        id: user_detail.id.clone(),
+        name: Some(new_name.clone()),
+        email: None,
+        workspace: None,
+        password: None,
+    };
+
+    let user_detail = UserTestBuilder::new()
+        .event(UpdateUser)
+        .request(request)
+        .sync_send()
+        .parse::<UserDetail>();
+
+    assert_eq!(user_detail.name, new_name,);
+}
+
+#[test]
+#[serial]
+fn user_update_with_email() {
+    let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
+    let new_email = "[email protected]".to_owned();
+    let request = UpdateUserRequest {
+        id: user_detail.id.clone(),
+        name: None,
+        email: Some(new_email.clone()),
+        workspace: None,
+        password: None,
+    };
+
+    let user_detail = UserTestBuilder::new()
+        .event(UpdateUser)
+        .request(request)
+        .sync_send()
+        .parse::<UserDetail>();
+
+    assert_eq!(user_detail.email, new_email,);
+}
+
+#[test]
+#[serial]
+fn user_update_with_password() {
+    let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
+    let new_password = "H123world!".to_owned();
+    let request = UpdateUserRequest {
+        id: user_detail.id.clone(),
+        name: None,
+        email: None,
+        workspace: None,
+        password: Some(new_password.clone()),
+    };
+
+    let _ = UserTestBuilder::new()
+        .event(UpdateUser)
+        .request(request)
+        .sync_send()
+        .assert_success();
+}
+
+#[test]
+#[serial]
+fn user_update_with_invalid_email() {
+    let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
+    for email in invalid_email_test_case() {
+        let request = UpdateUserRequest {
+            id: user_detail.id.clone(),
+            name: None,
+            email: Some(email),
+            workspace: None,
+            password: None,
+        };
+
+        assert_eq!(
+            UserTestBuilder::new()
+                .event(UpdateUser)
+                .request(request)
+                .sync_send()
+                .error()
+                .code,
+            UserErrorCode::EmailInvalid
+        );
+    }
+}
+
+#[test]
+#[serial]
+fn user_update_with_invalid_password() {
+    let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
+    for password in invalid_password_test_case() {
+        let request = UpdateUserRequest {
+            id: user_detail.id.clone(),
+            name: None,
+            email: None,
+            workspace: None,
+            password: Some(password),
+        };
+
+        assert_eq!(
+            UserTestBuilder::new()
+                .event(UpdateUser)
+                .request(request)
+                .sync_send()
+                .error()
+                .code,
+            UserErrorCode::PasswordInvalid
+        );
+    }
+}
+
+#[test]
+#[serial]
+fn user_update_with_invalid_name() {
+    let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
+    let request = UpdateUserRequest {
+        id: user_detail.id.clone(),
+        name: Some("".to_string()),
+        email: None,
+        workspace: None,
+        password: None,
+    };
+
+    assert_eq!(
+        UserTestBuilder::new()
+            .event(UpdateUser)
+            .request(request)
+            .sync_send()
+            .error()
+            .code,
+        UserErrorCode::UserNameInvalid
+    );
+}

+ 65 - 62
rust-lib/flowy-user/tests/event/sign_up_test.rs

@@ -1,62 +1,65 @@
-use crate::helper::*;
-use flowy_user::{errors::*, event::UserEvent::*, prelude::*};
-use serial_test::*;
-
-#[test]
-#[serial]
-fn sign_up_success() {
-    let _ = UserTestBuilder::new().event(SignOut).sync_send();
-    let request = SignUpRequest {
-        email: random_valid_email(),
-        name: valid_name(),
-        password: valid_password(),
-    };
-
-    let _response = UserTestBuilder::new()
-        .event(SignUp)
-        .request(request)
-        .sync_send();
-    // .parse::<SignUpResponse>();
-    // dbg!(&response);
-}
-
-#[test]
-fn sign_up_with_invalid_email() {
-    for email in invalid_email_test_case() {
-        let request = SignUpRequest {
-            email: email.to_string(),
-            name: valid_name(),
-            password: valid_password(),
-        };
-
-        assert_eq!(
-            UserTestBuilder::new()
-                .event(SignUp)
-                .request(request)
-                .sync_send()
-                .error()
-                .code,
-            UserErrorCode::EmailInvalid
-        );
-    }
-}
-#[test]
-fn sign_up_with_invalid_password() {
-    for password in invalid_password_test_case() {
-        let request = SignUpRequest {
-            email: random_valid_email(),
-            name: valid_name(),
-            password,
-        };
-
-        assert_eq!(
-            UserTestBuilder::new()
-                .event(SignUp)
-                .request(request)
-                .sync_send()
-                .error()
-                .code,
-            UserErrorCode::PasswordInvalid
-        );
-    }
-}
+// use crate::helper::*;
+// use flowy_user::{errors::*, event::UserEvent::*, prelude::*};
+// use serial_test::*;
+//
+// #[test]
+// #[serial]
+// fn sign_up_success() {
+//     let _ = UserTestBuilder::new().event(SignOut).sync_send();
+//     let request = SignUpRequest {
+//         email: random_valid_email(),
+//         name: valid_name(),
+//         password: valid_password(),
+//     };
+//
+//     let _response = UserTestBuilder::new()
+//         .logout()
+//         .event(SignUp)
+//         .request(request)
+//         .sync_send();
+//     // .parse::<SignUpResponse>();
+//     // dbg!(&response);
+// }
+//
+// #[test]
+// #[serial]
+// fn sign_up_with_invalid_email() {
+//     for email in invalid_email_test_case() {
+//         let request = SignUpRequest {
+//             email: email.to_string(),
+//             name: valid_name(),
+//             password: valid_password(),
+//         };
+//
+//         assert_eq!(
+//             UserTestBuilder::new()
+//                 .event(SignUp)
+//                 .request(request)
+//                 .sync_send()
+//                 .error()
+//                 .code,
+//             UserErrorCode::EmailInvalid
+//         );
+//     }
+// }
+// #[test]
+// #[serial]
+// fn sign_up_with_invalid_password() {
+//     for password in invalid_password_test_case() {
+//         let request = SignUpRequest {
+//             email: random_valid_email(),
+//             name: valid_name(),
+//             password,
+//         };
+//
+//         assert_eq!(
+//             UserTestBuilder::new()
+//                 .event(SignUp)
+//                 .request(request)
+//                 .sync_send()
+//                 .error()
+//                 .code,
+//             UserErrorCode::PasswordInvalid
+//         );
+//     }
+// }

+ 36 - 36
rust-lib/flowy-user/tests/event/user_status_test.rs

@@ -1,36 +1,36 @@
-use crate::helper::*;
-use flowy_user::{event::UserEvent::*, prelude::*};
-use serial_test::*;
-
-#[test]
-#[should_panic]
-#[serial]
-fn user_status_get_failed_before_login() {
-    let _ = UserTestBuilder::new()
-        .logout()
-        .event(GetStatus)
-        .sync_send()
-        .parse::<UserDetail>();
-}
-
-#[test]
-#[serial]
-fn user_status_get_success_after_login() {
-    let request = SignInRequest {
-        email: random_valid_email(),
-        password: valid_password(),
-    };
-
-    let response = UserTestBuilder::new()
-        .logout()
-        .event(SignIn)
-        .request(request)
-        .sync_send()
-        .parse::<UserDetail>();
-    dbg!(&response);
-
-    let _ = UserTestBuilder::new()
-        .event(GetStatus)
-        .sync_send()
-        .parse::<UserDetail>();
-}
+// use crate::helper::*;
+// use flowy_user::{event::UserEvent::*, prelude::*};
+// use serial_test::*;
+//
+// #[test]
+// #[should_panic]
+// #[serial]
+// fn user_status_get_failed_before_login() {
+//     let _ = UserTestBuilder::new()
+//         .logout()
+//         .event(GetStatus)
+//         .sync_send()
+//         .parse::<UserDetail>();
+// }
+//
+// #[test]
+// #[serial]
+// fn user_status_get_success_after_login() {
+//     let request = SignInRequest {
+//         email: random_valid_email(),
+//         password: valid_password(),
+//     };
+//
+//     let response = UserTestBuilder::new()
+//         .logout()
+//         .event(SignIn)
+//         .request(request)
+//         .sync_send()
+//         .parse::<UserDetail>();
+//     dbg!(&response);
+//
+//     let _ = UserTestBuilder::new()
+//         .event(GetStatus)
+//         .sync_send()
+//         .parse::<UserDetail>();
+// }

+ 140 - 140
rust-lib/flowy-user/tests/event/user_update_test.rs

@@ -1,140 +1,140 @@
-use crate::helper::*;
-use flowy_user::{errors::UserErrorCode, event::UserEvent::*, prelude::*};
-use serial_test::*;
-
-#[test]
-#[serial]
-fn user_update_with_name() {
-    let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
-    let new_name = "hello_world".to_owned();
-    let request = UpdateUserRequest {
-        id: user_detail.id.clone(),
-        name: Some(new_name.clone()),
-        email: None,
-        workspace: None,
-        password: None,
-    };
-
-    let user_detail = UserTestBuilder::new()
-        .event(UpdateUser)
-        .request(request)
-        .sync_send()
-        .parse::<UserDetail>();
-
-    assert_eq!(user_detail.name, new_name,);
-}
-
-#[test]
-#[serial]
-fn user_update_with_email() {
-    let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
-    let new_email = "[email protected]".to_owned();
-    let request = UpdateUserRequest {
-        id: user_detail.id.clone(),
-        name: None,
-        email: Some(new_email.clone()),
-        workspace: None,
-        password: None,
-    };
-
-    let user_detail = UserTestBuilder::new()
-        .event(UpdateUser)
-        .request(request)
-        .sync_send()
-        .parse::<UserDetail>();
-
-    assert_eq!(user_detail.email, new_email,);
-}
-
-#[test]
-#[serial]
-fn user_update_with_password() {
-    let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
-    let new_password = "H123world!".to_owned();
-    let request = UpdateUserRequest {
-        id: user_detail.id.clone(),
-        name: None,
-        email: None,
-        workspace: None,
-        password: Some(new_password.clone()),
-    };
-
-    let _ = UserTestBuilder::new()
-        .event(UpdateUser)
-        .request(request)
-        .sync_send()
-        .assert_success();
-}
-
-#[test]
-#[serial]
-fn user_update_with_invalid_email() {
-    let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
-    for email in invalid_email_test_case() {
-        let request = UpdateUserRequest {
-            id: user_detail.id.clone(),
-            name: None,
-            email: Some(email),
-            workspace: None,
-            password: None,
-        };
-
-        assert_eq!(
-            UserTestBuilder::new()
-                .event(UpdateUser)
-                .request(request)
-                .sync_send()
-                .error()
-                .code,
-            UserErrorCode::EmailInvalid
-        );
-    }
-}
-
-#[test]
-#[serial]
-fn user_update_with_invalid_password() {
-    let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
-    for password in invalid_password_test_case() {
-        let request = UpdateUserRequest {
-            id: user_detail.id.clone(),
-            name: None,
-            email: None,
-            workspace: None,
-            password: Some(password),
-        };
-
-        assert_eq!(
-            UserTestBuilder::new()
-                .event(UpdateUser)
-                .request(request)
-                .sync_send()
-                .error()
-                .code,
-            UserErrorCode::PasswordInvalid
-        );
-    }
-}
-
-#[test]
-#[serial]
-fn user_update_with_invalid_name() {
-    let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
-    let request = UpdateUserRequest {
-        id: user_detail.id.clone(),
-        name: Some("".to_string()),
-        email: None,
-        workspace: None,
-        password: None,
-    };
-
-    assert_eq!(
-        UserTestBuilder::new()
-            .event(UpdateUser)
-            .request(request)
-            .sync_send()
-            .error()
-            .code,
-        UserErrorCode::UserNameInvalid
-    );
-}
+// use crate::helper::*;
+// use flowy_user::{errors::UserErrorCode, event::UserEvent::*, prelude::*};
+// use serial_test::*;
+//
+// #[test]
+// #[serial]
+// fn user_update_with_name() {
+//     let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
+//     let new_name = "hello_world".to_owned();
+//     let request = UpdateUserRequest {
+//         id: user_detail.id.clone(),
+//         name: Some(new_name.clone()),
+//         email: None,
+//         workspace: None,
+//         password: None,
+//     };
+//
+//     let user_detail = UserTestBuilder::new()
+//         .event(UpdateUser)
+//         .request(request)
+//         .sync_send()
+//         .parse::<UserDetail>();
+//
+//     assert_eq!(user_detail.name, new_name,);
+// }
+//
+// #[test]
+// #[serial]
+// fn user_update_with_email() {
+//     let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
+//     let new_email = "[email protected]".to_owned();
+//     let request = UpdateUserRequest {
+//         id: user_detail.id.clone(),
+//         name: None,
+//         email: Some(new_email.clone()),
+//         workspace: None,
+//         password: None,
+//     };
+//
+//     let user_detail = UserTestBuilder::new()
+//         .event(UpdateUser)
+//         .request(request)
+//         .sync_send()
+//         .parse::<UserDetail>();
+//
+//     assert_eq!(user_detail.email, new_email,);
+// }
+//
+// #[test]
+// #[serial]
+// fn user_update_with_password() {
+//     let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
+//     let new_password = "H123world!".to_owned();
+//     let request = UpdateUserRequest {
+//         id: user_detail.id.clone(),
+//         name: None,
+//         email: None,
+//         workspace: None,
+//         password: Some(new_password.clone()),
+//     };
+//
+//     let _ = UserTestBuilder::new()
+//         .event(UpdateUser)
+//         .request(request)
+//         .sync_send()
+//         .assert_success();
+// }
+//
+// #[test]
+// #[serial]
+// fn user_update_with_invalid_email() {
+//     let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
+//     for email in invalid_email_test_case() {
+//         let request = UpdateUserRequest {
+//             id: user_detail.id.clone(),
+//             name: None,
+//             email: Some(email),
+//             workspace: None,
+//             password: None,
+//         };
+//
+//         assert_eq!(
+//             UserTestBuilder::new()
+//                 .event(UpdateUser)
+//                 .request(request)
+//                 .sync_send()
+//                 .error()
+//                 .code,
+//             UserErrorCode::EmailInvalid
+//         );
+//     }
+// }
+//
+// #[test]
+// #[serial]
+// fn user_update_with_invalid_password() {
+//     let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
+//     for password in invalid_password_test_case() {
+//         let request = UpdateUserRequest {
+//             id: user_detail.id.clone(),
+//             name: None,
+//             email: None,
+//             workspace: None,
+//             password: Some(password),
+//         };
+//
+//         assert_eq!(
+//             UserTestBuilder::new()
+//                 .event(UpdateUser)
+//                 .request(request)
+//                 .sync_send()
+//                 .error()
+//                 .code,
+//             UserErrorCode::PasswordInvalid
+//         );
+//     }
+// }
+//
+// #[test]
+// #[serial]
+// fn user_update_with_invalid_name() {
+//     let user_detail = UserTestBuilder::new().login().user_detail.unwrap();
+//     let request = UpdateUserRequest {
+//         id: user_detail.id.clone(),
+//         name: Some("".to_string()),
+//         email: None,
+//         workspace: None,
+//         password: None,
+//     };
+//
+//     assert_eq!(
+//         UserTestBuilder::new()
+//             .event(UpdateUser)
+//             .request(request)
+//             .sync_send()
+//             .error()
+//             .code,
+//         UserErrorCode::UserNameInvalid
+//     );
+// }