Kaynağa Gözat

config flowy-user test

appflowy 3 yıl önce
ebeveyn
işleme
678dd84f93

+ 1 - 0
.idea/appflowy_client.iml

@@ -11,6 +11,7 @@
       <sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-log/src" isTestSource="false" />
       <sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-sdk/src" isTestSource="false" />
       <sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-user/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-sdk/tests" isTestSource="true" />
       <excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/af_protobuf/.pub" />
       <excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/af_protobuf/.dart_tool" />
       <excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/af_protobuf/build" />

+ 0 - 1
rust-lib/dart-ffi/src/c.rs

@@ -1,5 +1,4 @@
 use byteorder::{BigEndian, ByteOrder};
-use flowy_protobuf::ResponsePacket;
 use std::mem::{forget, size_of};
 
 pub fn forget_rust(buf: Vec<u8>) -> *const u8 {

+ 24 - 10
rust-lib/dart-ffi/src/lib.rs

@@ -13,23 +13,37 @@ pub extern "C" fn init_sdk(path: *mut c_char) -> i64 {
     return 1;
 }
 
+pub struct FFICommand {
+    event: String,
+    payload: Vec<u8>,
+}
+
+impl FFICommand {
+    pub fn from_bytes(bytes: Vec<u8>) -> Self { unimplemented!() }
+
+    pub fn from_u8_pointer(pointer: *const u8, len: usize) -> Self {
+        let bytes = unsafe { std::slice::from_raw_parts(pointer, len) }.to_vec();
+        unimplemented!()
+    }
+}
+
 #[no_mangle]
 pub extern "C" fn async_command(port: i64, input: *const u8, len: usize) {
-    let bytes = unsafe { std::slice::from_raw_parts(input, len) }.to_vec();
-    let payload = SenderPayload::from_data(bytes);
+    let FFICommand { event, payload } = FFICommand::from_u8_pointer(input, len);
+
+    let mut request = SenderRequest::new(port, event).callback(|_, resp| {
+        log::info!("async resp: {:?}", resp);
+    });
 
-    let stream_data = SenderData::new(port, payload).callback(Box::new(|_config, response| {
-        log::info!("async resp: {:?}", response);
-    }));
+    if !payload.is_empty() {
+        request = request.payload(Payload::Bytes(bytes));
+    }
 
-    async_send(stream_data);
+    async_send(request);
 }
 
 #[no_mangle]
-pub extern "C" fn sync_command(input: *const u8, len: usize) -> *const u8 {
-    let bytes = unsafe { std::slice::from_raw_parts(input, len) }.to_vec();
-    forget_rust(bytes)
-}
+pub extern "C" fn sync_command(input: *const u8, len: usize) -> *const u8 { unimplemented!() }
 
 #[inline(never)]
 #[no_mangle]

+ 12 - 1
rust-lib/flowy-sdk/Cargo.toml

@@ -7,4 +7,15 @@ edition = "2018"
 
 [dependencies]
 flowy-sys = { path = "../flowy-sys" }
-flowy-log = { path = "../flowy-log" }
+flowy-log = { path = "../flowy-log" }
+flowy-user = { path = "../flowy-user" }
+
+log = "0.4.14"
+
+[dev-dependencies]
+serde = { version = "1.0", features = ["derive"] }
+bincode = { version = "1.3"}
+protobuf = {version = "2.24.1"}
+claim = "0.5.0"
+tokio = { version = "1", features = ["full"]}
+futures-util = "0.3.15"

+ 14 - 13
rust-lib/flowy-sdk/src/lib.rs

@@ -1,21 +1,24 @@
+pub mod module;
+pub use module::*;
+
 use flowy_sys::prelude::*;
+use module::build_modules;
 use std::cell::RefCell;
-
 pub struct FlowySDK {}
 
 impl FlowySDK {
     pub fn init(path: &str) {
-        let modules = init_modules();
-        init_system(modules);
-    }
-}
+        flowy_log::init_log("flowy", "Debug").unwrap();
 
-pub fn init_modules() -> Vec<Module> {
-    let modules = vec![];
-    modules
+        log::info!("🔥🔥🔥 System start running");
+        match init_system(build_modules()).run() {
+            Ok(_) => {},
+            Err(e) => log::error!("System run fail with error: {:?}", e),
+        }
+    }
 }
 
-pub fn init_system<F>(modules: Vec<Module>) {
+pub fn init_system(modules: Vec<Module>) -> SystemRunner {
     FlowySystem::construct(
         || modules,
         |module_map, runtime| {
@@ -27,22 +30,20 @@ pub fn init_system<F>(modules: Vec<Module>) {
             });
         },
     )
-    .run()
-    .unwrap();
 }
 
 thread_local!(
     static SENDER: RefCell<Option<Sender<i64>>> = RefCell::new(None);
 );
 
-pub fn sync_send(data: SenderData<i64>) -> EventResponse {
+pub fn sync_send(data: SenderRequest<i64>) -> EventResponse {
     SENDER.with(|cell| match &*cell.borrow() {
         Some(stream) => stream.sync_send(data),
         None => panic!(""),
     })
 }
 
-pub fn async_send(data: SenderData<i64>) {
+pub fn async_send(data: SenderRequest<i64>) {
     SENDER.with(|cell| match &*cell.borrow() {
         Some(stream) => {
             stream.async_send(data);

+ 3 - 0
rust-lib/flowy-sdk/src/module.rs

@@ -0,0 +1,3 @@
+use flowy_sys::prelude::Module;
+
+pub fn build_modules() -> Vec<Module> { vec![flowy_user::module::create()] }

+ 85 - 0
rust-lib/flowy-sdk/tests/sdk/helper.rs

@@ -0,0 +1,85 @@
+use flowy_sdk::module::build_modules;
+pub use flowy_sdk::*;
+use flowy_sys::prelude::*;
+use std::{
+    fmt::{Debug, Display},
+    hash::Hash,
+    sync::Once,
+};
+
+static INIT: Once = Once::new();
+pub fn run_test_system<F>(f: F)
+where
+    F: FnOnce() + 'static,
+{
+    INIT.call_once(|| {
+        flowy_log::init_log("flowy", "Debug").unwrap();
+    });
+
+    let mut runner = init_system(build_modules());
+    runner = runner.spawn(async {
+        f();
+        FlowySystem::current().stop();
+    });
+
+    log::info!("🔥🔥🔥 System start running");
+    match runner.run() {
+        Ok(_) => {},
+        Err(e) => log::error!("System run fail with error: {:?}", e),
+    }
+}
+
+pub struct FlowySDKTester {
+    request: SenderRequest<i64>,
+    callback: Option<BoxStreamCallback<i64>>,
+}
+
+impl FlowySDKTester {
+    pub fn new<E>(event: E) -> Self
+    where
+        E: Eq + Hash + Debug + Clone + Display,
+    {
+        Self {
+            request: SenderRequest::new(1, event),
+            callback: None,
+        }
+    }
+
+    #[allow(dead_code)]
+    pub fn bytes_payload<T>(mut self, payload: T) -> Self
+    where
+        T: serde::Serialize,
+    {
+        let bytes: Vec<u8> = bincode::serialize(&payload).unwrap();
+        self.request = self.request.payload(Payload::Bytes(bytes));
+        self
+    }
+
+    #[allow(dead_code)]
+    pub fn protobuf_payload<T>(mut self, payload: T) -> Self
+    where
+        T: ::protobuf::Message,
+    {
+        let bytes: Vec<u8> = payload.write_to_bytes().unwrap();
+        self.request = self.request.payload(Payload::Bytes(bytes));
+        self
+    }
+
+    #[allow(dead_code)]
+    pub fn callback<F>(mut self, callback: F) -> Self
+    where
+        F: FnOnce(i64, EventResponse) + 'static + Send + Sync,
+    {
+        self.request = self.request.callback(|config, response| {
+            dbg!(&response);
+            callback(config, response);
+        });
+        self
+    }
+
+    pub fn run(self) {
+        run_test_system(move || {
+            async_send(self.request);
+        });
+    }
+}

+ 2 - 0
rust-lib/flowy-sdk/tests/sdk/main.rs

@@ -0,0 +1,2 @@
+mod helper;
+mod user_check;

+ 26 - 0
rust-lib/flowy-sdk/tests/sdk/user_check.rs

@@ -0,0 +1,26 @@
+use super::helper::*;
+use flowy_sys::prelude::*;
+use flowy_user::prelude::*;
+
+#[test]
+fn auth_check_no_payload() {
+    let callback = |_, resp: EventResponse| {
+        assert_eq!(resp.status, StatusCode::Err);
+    };
+
+    FlowySDKTester::new(AuthCheck).callback(callback).run();
+}
+
+#[test]
+fn auth_check_with_user_name_email_payload() {
+    let callback = |_, resp: EventResponse| {
+        assert_eq!(resp.status, StatusCode::Ok);
+    };
+
+    let user_data = UserData::new("jack".to_owned(), "[email protected]".to_owned());
+
+    FlowySDKTester::new(AuthCheck)
+        .bytes_payload(user_data)
+        .callback(callback)
+        .run();
+}

+ 1 - 0
rust-lib/flowy-sys/Cargo.toml

@@ -21,6 +21,7 @@ serde_with = "1.9.4"
 thread-id = "3.3.0"
 lazy_static = "1.4.0"
 dyn-clone = "1.0"
+derivative = "2.2.0"
 
 #optional crate
 bincode = { version = "1.3", optional = true}

+ 18 - 3
rust-lib/flowy-sys/src/error/error.rs

@@ -7,7 +7,7 @@ use std::{fmt, option::NoneError};
 use tokio::sync::mpsc::error::SendError;
 
 #[cfg(feature = "use_serde")]
-use serde::{Deserialize, Serialize, Serializer};
+use serde::{Serialize, Serializer};
 
 pub trait Error: fmt::Debug + fmt::Display + DynClone {
     fn status_code(&self) -> StatusCode;
@@ -18,7 +18,11 @@ pub trait Error: fmt::Debug + fmt::Display + DynClone {
 dyn_clone::clone_trait_object!(Error);
 
 impl<T: Error + 'static> From<T> for SystemError {
-    fn from(err: T) -> SystemError { SystemError { inner: Box::new(err) } }
+    fn from(err: T) -> SystemError {
+        SystemError {
+            inner: Box::new(err),
+        }
+    }
 }
 
 #[derive(Clone)]
@@ -62,6 +66,10 @@ impl From<NoneError> for SystemError {
     }
 }
 
+impl From<String> for SystemError {
+    fn from(s: String) -> Self { InternalError { inner: s }.into() }
+}
+
 impl From<SystemError> for EventResponse {
     fn from(err: SystemError) -> Self { err.inner_error().as_response() }
 }
@@ -95,7 +103,14 @@ where
 {
     fn status_code(&self) -> StatusCode { StatusCode::Err }
 
-    fn as_response(&self) -> EventResponse { EventResponseBuilder::Err().data(format!("{}", self.inner)).build() }
+    fn as_response(&self) -> EventResponse {
+        let error = InternalError {
+            inner: format!("{}", self.inner),
+        }
+        .into();
+
+        EventResponseBuilder::Err().error(error).build()
+    }
 }
 
 #[cfg(feature = "use_serde")]

+ 0 - 5
rust-lib/flowy-sys/src/request/payload.rs

@@ -1,8 +1,3 @@
-use std::pin::Pin;
-
-use bytes::Bytes;
-use futures::Stream;
-
 pub enum PayloadError {}
 
 // TODO: support stream data

+ 14 - 8
rust-lib/flowy-sys/src/request/request.rs

@@ -3,14 +3,14 @@ use std::future::Future;
 use crate::{
     error::{InternalError, SystemError},
     module::Event,
-    request::{payload::Payload, PayloadError},
+    request::payload::Payload,
     response::Responder,
     util::ready::{ready, Ready},
 };
-use bytes::Bytes;
-use futures_core::{ready, Stream};
+
+use futures_core::ready;
 use std::{
-    fmt::{Debug, Display},
+    fmt::Debug,
     hash::Hash,
     ops,
     pin::Pin,
@@ -57,13 +57,19 @@ impl FromRequest for String {
 
     fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future {
         match &payload {
-            Payload::None => ready(Err(unexpected_none_payload())),
+            Payload::None => ready(Err(unexpected_none_payload(req))),
             Payload::Bytes(buf) => ready(Ok(String::from_utf8_lossy(buf).into_owned())),
         }
     }
 }
 
-fn unexpected_none_payload() -> SystemError { InternalError::new("Expected string but request had data").into() }
+fn unexpected_none_payload(request: &EventRequest) -> SystemError {
+    log::warn!(
+        "Event: {:?} expected payload but payload is empty",
+        &request.event
+    );
+    InternalError::new("Expected payload but payload is empty").into()
+}
 
 #[doc(hidden)]
 impl<T> FromRequest for Result<T, T::Error>
@@ -126,7 +132,7 @@ where
     #[inline]
     fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future {
         match payload {
-            Payload::None => ready(Err(unexpected_none_payload())),
+            Payload::None => ready(Err(unexpected_none_payload(req))),
             Payload::Bytes(bytes) => {
                 let data: T = bincode::deserialize(bytes).unwrap();
                 ready(Ok(In(data)))
@@ -146,7 +152,7 @@ where
     #[inline]
     fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future {
         match payload {
-            Payload::None => ready(Err(unexpected_none_payload())),
+            Payload::None => ready(Err(unexpected_none_payload(req))),
             Payload::Bytes(bytes) => {
                 let data: T = ::protobuf::Message::parse_from_bytes(bytes).unwrap();
                 ready(Ok(In(data)))

+ 2 - 2
rust-lib/flowy-sys/src/response/builder.rs

@@ -30,8 +30,8 @@ impl EventResponseBuilder {
         self
     }
 
-    pub fn error(mut self, error: Option<SystemError>) -> Self {
-        self.error = error;
+    pub fn error(mut self, error: SystemError) -> Self {
+        self.error = Some(error);
         self
     }
 

+ 19 - 1
rust-lib/flowy-sys/src/response/responder.rs

@@ -13,7 +13,9 @@ pub trait Responder {
 macro_rules! impl_responder {
     ($res: ty) => {
         impl Responder for $res {
-            fn respond_to(self, _: &EventRequest) -> EventResponse { EventResponseBuilder::Ok().data(self).build() }
+            fn respond_to(self, _: &EventRequest) -> EventResponse {
+                EventResponseBuilder::Ok().data(self).build()
+            }
         }
     };
 }
@@ -63,6 +65,14 @@ where
     }
 }
 
+#[cfg(feature = "use_serde")]
+impl<T> std::convert::From<T> for Out<T>
+where
+    T: serde::Serialize,
+{
+    fn from(val: T) -> Self { Out(val) }
+}
+
 #[cfg(feature = "use_protobuf")]
 impl<T> Responder for Out<T>
 where
@@ -73,3 +83,11 @@ where
         EventResponseBuilder::Ok().data(bytes).build()
     }
 }
+
+#[cfg(feature = "use_protobuf")]
+impl<T> std::convert::From<T> for Out<T>
+where
+    T: ::protobuf::Message,
+{
+    fn from(val: T) -> Self { Out(val) }
+}

+ 3 - 3
rust-lib/flowy-sys/src/response/response.rs

@@ -8,11 +8,11 @@ use crate::{
 use serde::{Deserialize, Serialize, Serializer};
 use std::{fmt, fmt::Formatter};
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Eq, PartialEq)]
 #[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
 pub enum StatusCode {
-    Ok,
-    Err,
+    Ok  = 0,
+    Err = 1,
 }
 
 // serde user guide: https://serde.rs/field-attrs.html

+ 77 - 49
rust-lib/flowy-sys/src/sender/data.rs

@@ -1,71 +1,99 @@
-use crate::{
-    module::{Event, ModuleRequest},
-    request::{EventRequest, Payload},
-    response::EventResponse,
-};
+use crate::{module::Event, request::Payload, response::EventResponse};
+use derivative::*;
 use std::{
     fmt::{Debug, Display},
     hash::Hash,
 };
+// #[derive(Debug)]
+// pub struct SenderPayload {
+//     pub(crate) payload: Payload,
+//     pub(crate) event: Event,
+// }
+//
+// impl SenderPayload {
+//     pub fn new<E>(event: E) -> SenderPayload
+//     where
+//         E: Eq + Hash + Debug + Clone + Display,
+//     {
+//         Self {
+//             event: event.into(),
+//             payload: Payload::None,
+//         }
+//     }
+//
+//     pub fn payload(mut self, payload: Payload) -> Self {
+//         self.payload = payload;
+//         self
+//     }
+//
+//     pub fn from_bytes(bytes: Vec<u8>) -> Self { unimplemented!() }
+// }
+//
+// impl std::convert::Into<ModuleRequest> for SenderPayload {
+//     fn into(self) -> ModuleRequest {
+// ModuleRequest::new(self.event).payload(self.payload) } }
+//
+// impl std::default::Default for SenderPayload {
+//     fn default() -> Self { SenderPayload::new("").payload(Payload::None) }
+// }
+//
+// impl std::convert::Into<EventRequest> for SenderPayload {
+//     fn into(self) -> EventRequest { unimplemented!() }
+// }
 
-#[derive(Debug)]
-pub struct SenderPayload {
-    pub(crate) payload: Payload,
-    pub(crate) event: Event,
-}
-
-impl SenderPayload {
-    pub fn new<E>(event: E) -> SenderPayload
-    where
-        E: Eq + Hash + Debug + Clone + Display,
-    {
-        Self {
-            event: event.into(),
-            payload: Payload::None,
-        }
-    }
-
-    pub fn payload(mut self, payload: Payload) -> Self {
-        self.payload = payload;
-        self
-    }
-
-    pub fn from_bytes(bytes: Vec<u8>) -> Self { unimplemented!() }
-}
-
-impl std::convert::Into<ModuleRequest> for SenderPayload {
-    fn into(self) -> ModuleRequest { ModuleRequest::new(self.event).payload(self.payload) }
-}
+pub type BoxStreamCallback<T> = Box<dyn FnOnce(T, EventResponse) + 'static + Send + Sync>;
 
-impl std::default::Default for SenderPayload {
-    fn default() -> Self { SenderPayload::new("").payload(Payload::None) }
-}
+// #[derive(Debug)]
+// pub struct SenderRequest2<T, C>
+// where
+//     T: 'static + Debug,
+//     C: FnOnce(T, EventResponse) + 'static,
+// {
+//     pub config: T,
+//     pub event: Event,
+//     pub payload: Option<Payload>,
+//     pub callback: Box<dyn C>,
+// }
 
-impl std::convert::Into<EventRequest> for SenderPayload {
-    fn into(self) -> EventRequest { unimplemented!() }
-}
-
-pub type BoxStreamCallback<T> = Box<dyn FnOnce(T, EventResponse) + 'static + Send + Sync>;
-pub struct SenderData<T>
+#[derive(Derivative)]
+#[derivative(Debug)]
+pub struct SenderRequest<T>
 where
-    T: 'static,
+    T: 'static + Debug,
 {
     pub config: T,
-    pub payload: SenderPayload,
+    pub event: Event,
+    pub payload: Option<Payload>,
+    #[derivative(Debug = "ignore")]
     pub callback: Option<BoxStreamCallback<T>>,
 }
 
-impl<T> SenderData<T> {
-    pub fn new(config: T, payload: SenderPayload) -> Self {
+impl<T> SenderRequest<T>
+where
+    T: 'static + Debug,
+{
+    pub fn new<E>(config: T, event: E) -> Self
+    where
+        E: Eq + Hash + Debug + Clone + Display,
+    {
         Self {
             config,
-            payload,
+            payload: None,
+            event: event.into(),
             callback: None,
         }
     }
 
-    pub fn callback(mut self, callback: BoxStreamCallback<T>) -> Self {
-        self.callback = Some(callback);
+    pub fn payload(mut self, payload: Payload) -> Self {
+        self.payload = Some(payload);
+        self
+    }
+
+    pub fn callback<F>(mut self, callback: F) -> Self
+    where
+        F: FnOnce(T, EventResponse) + 'static + Send + Sync,
+    {
+        self.callback = Some(Box::new(callback));
         self
     }
 }

+ 28 - 25
rust-lib/flowy-sys/src/sender/sender.rs

@@ -1,14 +1,14 @@
 use crate::{
     error::{InternalError, SystemError},
-    module::{Event, ModuleRequest},
+    module::ModuleRequest,
     request::{EventRequest, Payload},
     response::EventResponse,
-    sender::{SenderData, SenderPayload},
+    sender::SenderRequest,
     service::{BoxService, Service, ServiceFactory},
     system::ModuleMap,
 };
 use futures_core::{future::LocalBoxFuture, ready, task::Context};
-use std::future::Future;
+use std::{fmt::Debug, future::Future};
 use tokio::{
     macros::support::{Pin, Poll},
     sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
@@ -17,13 +17,13 @@ use tokio::{
 macro_rules! service_factor_impl {
     ($name:ident) => {
         #[allow(non_snake_case, missing_docs)]
-        impl<T> ServiceFactory<SenderData<T>> for $name<T>
+        impl<T> ServiceFactory<SenderRequest<T>> for $name<T>
         where
-            T: 'static,
+            T: 'static + Debug,
         {
             type Response = EventResponse;
             type Error = SystemError;
-            type Service = BoxService<SenderData<T>, Self::Response, Self::Error>;
+            type Service = BoxService<SenderRequest<T>, Self::Response, Self::Error>;
             type Context = ();
             type Future = LocalBoxFuture<'static, Result<Self::Service, Self::Error>>;
 
@@ -40,24 +40,27 @@ struct SenderService {
     module_map: ModuleMap,
 }
 
-impl<T> Service<SenderData<T>> for SenderService
+impl<T> Service<SenderRequest<T>> for SenderService
 where
-    T: 'static,
+    T: 'static + Debug,
 {
     type Response = EventResponse;
     type Error = SystemError;
     type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
 
-    fn call(&self, data: SenderData<T>) -> Self::Future {
+    fn call(&self, data: SenderRequest<T>) -> Self::Future {
         let module_map = self.module_map.clone();
-        let SenderData {
+        let SenderRequest {
             config,
+            event,
             payload,
             callback,
         } = data;
 
-        let event = payload.event.clone();
-        let request = payload.into();
+        let mut request = ModuleRequest::new(event.clone());
+        if let Some(payload) = payload {
+            request = request.payload(payload);
+        }
 
         let fut = async move {
             let result = {
@@ -87,21 +90,21 @@ where
 
 pub struct Sender<T>
 where
-    T: 'static,
+    T: 'static + Debug,
 {
     module_map: ModuleMap,
-    data_tx: UnboundedSender<SenderData<T>>,
-    data_rx: Option<UnboundedReceiver<SenderData<T>>>,
+    data_tx: UnboundedSender<SenderRequest<T>>,
+    data_rx: Option<UnboundedReceiver<SenderRequest<T>>>,
 }
 
 service_factor_impl!(Sender);
 
 impl<T> Sender<T>
 where
-    T: 'static,
+    T: 'static + Debug,
 {
     pub fn new(module_map: ModuleMap) -> Self {
-        let (data_tx, data_rx) = unbounded_channel::<SenderData<T>>();
+        let (data_tx, data_rx) = unbounded_channel::<SenderRequest<T>>();
         Self {
             module_map,
             data_tx,
@@ -109,9 +112,9 @@ where
         }
     }
 
-    pub fn async_send(&self, data: SenderData<T>) { let _ = self.data_tx.send(data); }
+    pub fn async_send(&self, data: SenderRequest<T>) { let _ = self.data_tx.send(data); }
 
-    pub fn sync_send(&self, data: SenderData<T>) -> EventResponse {
+    pub fn sync_send(&self, data: SenderRequest<T>) -> EventResponse {
         let factory = self.new_service(());
 
         futures::executor::block_on(async {
@@ -120,31 +123,31 @@ where
         })
     }
 
-    pub fn take_rx(&mut self) -> UnboundedReceiver<SenderData<T>> { self.data_rx.take().unwrap() }
+    pub fn take_rx(&mut self) -> UnboundedReceiver<SenderRequest<T>> { self.data_rx.take().unwrap() }
 }
 
 pub struct SenderRunner<T>
 where
-    T: 'static,
+    T: 'static + Debug,
 {
     module_map: ModuleMap,
-    data_rx: UnboundedReceiver<SenderData<T>>,
+    data_rx: UnboundedReceiver<SenderRequest<T>>,
 }
 
 service_factor_impl!(SenderRunner);
 
 impl<T> SenderRunner<T>
 where
-    T: 'static,
+    T: 'static + Debug,
 {
-    pub fn new(module_map: ModuleMap, data_rx: UnboundedReceiver<SenderData<T>>) -> Self {
+    pub fn new(module_map: ModuleMap, data_rx: UnboundedReceiver<SenderRequest<T>>) -> Self {
         Self { module_map, data_rx }
     }
 }
 
 impl<T> Future for SenderRunner<T>
 where
-    T: 'static,
+    T: 'static + Debug,
 {
     type Output = ();
     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {

+ 3 - 9
rust-lib/flowy-sys/tests/api/helper.rs

@@ -1,4 +1,4 @@
-use flowy_sys::prelude::{EventResponse, FlowySystem, Module, Sender, SenderData, SenderRunner};
+use flowy_sys::prelude::{EventResponse, FlowySystem, Module, Sender, SenderRequest, SenderRunner};
 use std::{cell::RefCell, sync::Once};
 
 #[allow(dead_code)]
@@ -10,24 +10,18 @@ pub fn setup_env() {
     });
 }
 
-pub struct ExecutorAction {
-    command: String,
-}
-
-pub struct FlowySystemExecutor {}
-
 thread_local!(
     static SENDER: RefCell<Option<Sender<i64>>> = RefCell::new(None);
 );
 
-pub fn sync_send(data: SenderData<i64>) -> EventResponse {
+pub fn sync_send(data: SenderRequest<i64>) -> EventResponse {
     SENDER.with(|cell| match &*cell.borrow() {
         Some(stream) => stream.sync_send(data),
         None => panic!(""),
     })
 }
 
-pub fn async_send(data: SenderData<i64>) {
+pub fn async_send(data: SenderRequest<i64>) {
     SENDER.with(|cell| match &*cell.borrow() {
         Some(stream) => {
             stream.async_send(data);

+ 3 - 6
rust-lib/flowy-sys/tests/api/module.rs

@@ -10,15 +10,12 @@ fn test_init() {
     let modules = vec![Module::new().event(event, hello)];
 
     init_system(modules, move || {
-        let payload = SenderPayload::new(event);
-
-        let stream_data = SenderData::new(1, payload).callback(Box::new(|_config, response| {
+        let request = SenderRequest::new(1, event).callback(|_config, response| {
             log::info!("async resp: {:?}", response);
-        }));
+        });
 
-        let resp = sync_send(stream_data);
+        let resp = sync_send(request);
         log::info!("sync resp: {:?}", resp);
-
         stop_system();
     });
 }

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

@@ -15,6 +15,7 @@ serde = { version = "1.0", features = ["derive"] }
 validator = "0.12.0"
 rand = { version = "0.8", features=["std_rng"] }
 unicode-segmentation = "1.7.1"
+log = "0.4.14"
 
 [dev-dependencies]
 quickcheck = "0.9.2"

+ 3 - 0
rust-lib/flowy-user/src/event.rs

@@ -4,7 +4,10 @@ use derive_more::Display;
 pub enum UserEvent {
     #[display(fmt = "AuthCheck")]
     AuthCheck = 0,
+    #[display(fmt = "SignIn")]
     SignIn    = 1,
+    #[display(fmt = "SignUp")]
     SignUp    = 2,
+    #[display(fmt = "SignOut")]
     SignOut   = 3,
 }

+ 14 - 1
rust-lib/flowy-user/src/handlers/auth.rs

@@ -12,7 +12,16 @@ use std::convert::TryInto;
         name = %data.name
     )
 )]
-pub async fn user_check(data: In<UserData>) -> Out<UserData> { panic!("") }
+pub async fn user_check(data: In<UserData>) -> Result<Out<UserStatus>, String> {
+    let user: User = data.into_inner().try_into()?;
+
+    Ok(UserStatus { is_login: false }.into())
+}
+
+#[derive(serde::Serialize)]
+pub struct UserStatus {
+    is_login: bool,
+}
 
 #[derive(Debug, serde::Deserialize, serde::Serialize)]
 pub struct UserData {
@@ -20,6 +29,10 @@ pub struct UserData {
     email: String,
 }
 
+impl UserData {
+    pub fn new(name: String, email: String) -> Self { Self { name, email } }
+}
+
 impl TryInto<User> for UserData {
     type Error = String;
 

+ 1 - 1
rust-lib/flowy-user/src/handlers/mod.rs

@@ -1,3 +1,3 @@
-mod auth;
+pub mod auth;
 
 pub use auth::*;

+ 9 - 1
rust-lib/flowy-user/src/lib.rs

@@ -1,5 +1,13 @@
 mod domain;
 mod error;
-mod event;
+pub mod event;
 mod handlers;
 pub mod module;
+
+pub mod prelude {
+    pub use crate::{
+        domain::*,
+        event::{UserEvent::*, *},
+        handlers::auth::*,
+    };
+}

+ 1 - 1
rust-lib/rustfmt.toml

@@ -1,5 +1,5 @@
 # https://rust-lang.github.io/rustfmt/?version=master&search=
-max_width = 120
+max_width = 100
 tab_spaces = 4
 fn_single_line = true
 match_block_trailing_comma = true