mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
config flowy-user test
This commit is contained in:
parent
f73b3ded1d
commit
678dd84f93
@ -11,6 +11,7 @@
|
|||||||
<sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-log/src" isTestSource="false" />
|
<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-sdk/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/rust-lib/flowy-user/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/.pub" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/af_protobuf/.dart_tool" />
|
<excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/af_protobuf/.dart_tool" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/af_protobuf/build" />
|
<excludeFolder url="file://$MODULE_DIR$/app_flowy/packages/af_protobuf/build" />
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use byteorder::{BigEndian, ByteOrder};
|
use byteorder::{BigEndian, ByteOrder};
|
||||||
use flowy_protobuf::ResponsePacket;
|
|
||||||
use std::mem::{forget, size_of};
|
use std::mem::{forget, size_of};
|
||||||
|
|
||||||
pub fn forget_rust(buf: Vec<u8>) -> *const u8 {
|
pub fn forget_rust(buf: Vec<u8>) -> *const u8 {
|
||||||
|
@ -13,23 +13,37 @@ pub extern "C" fn init_sdk(path: *mut c_char) -> i64 {
|
|||||||
return 1;
|
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]
|
#[no_mangle]
|
||||||
pub extern "C" fn async_command(port: i64, input: *const u8, len: usize) {
|
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 FFICommand { event, payload } = FFICommand::from_u8_pointer(input, len);
|
||||||
let payload = SenderPayload::from_data(bytes);
|
|
||||||
|
|
||||||
let stream_data = SenderData::new(port, payload).callback(Box::new(|_config, response| {
|
let mut request = SenderRequest::new(port, event).callback(|_, resp| {
|
||||||
log::info!("async resp: {:?}", response);
|
log::info!("async resp: {:?}", resp);
|
||||||
}));
|
});
|
||||||
|
|
||||||
async_send(stream_data);
|
if !payload.is_empty() {
|
||||||
|
request = request.payload(Payload::Bytes(bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
async_send(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn sync_command(input: *const u8, len: usize) -> *const u8 {
|
pub extern "C" fn sync_command(input: *const u8, len: usize) -> *const u8 { unimplemented!() }
|
||||||
let bytes = unsafe { std::slice::from_raw_parts(input, len) }.to_vec();
|
|
||||||
forget_rust(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -8,3 +8,14 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
flowy-sys = { path = "../flowy-sys" }
|
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"
|
@ -1,21 +1,24 @@
|
|||||||
use flowy_sys::prelude::*;
|
pub mod module;
|
||||||
use std::cell::RefCell;
|
pub use module::*;
|
||||||
|
|
||||||
|
use flowy_sys::prelude::*;
|
||||||
|
use module::build_modules;
|
||||||
|
use std::cell::RefCell;
|
||||||
pub struct FlowySDK {}
|
pub struct FlowySDK {}
|
||||||
|
|
||||||
impl FlowySDK {
|
impl FlowySDK {
|
||||||
pub fn init(path: &str) {
|
pub fn init(path: &str) {
|
||||||
let modules = init_modules();
|
flowy_log::init_log("flowy", "Debug").unwrap();
|
||||||
init_system(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_modules() -> Vec<Module> {
|
pub fn init_system(modules: Vec<Module>) -> SystemRunner {
|
||||||
let modules = vec![];
|
|
||||||
modules
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init_system<F>(modules: Vec<Module>) {
|
|
||||||
FlowySystem::construct(
|
FlowySystem::construct(
|
||||||
|| modules,
|
|| modules,
|
||||||
|module_map, runtime| {
|
|module_map, runtime| {
|
||||||
@ -27,22 +30,20 @@ pub fn init_system<F>(modules: Vec<Module>) {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.run()
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_local!(
|
thread_local!(
|
||||||
static SENDER: RefCell<Option<Sender<i64>>> = RefCell::new(None);
|
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() {
|
SENDER.with(|cell| match &*cell.borrow() {
|
||||||
Some(stream) => stream.sync_send(data),
|
Some(stream) => stream.sync_send(data),
|
||||||
None => panic!(""),
|
None => panic!(""),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn async_send(data: SenderData<i64>) {
|
pub fn async_send(data: SenderRequest<i64>) {
|
||||||
SENDER.with(|cell| match &*cell.borrow() {
|
SENDER.with(|cell| match &*cell.borrow() {
|
||||||
Some(stream) => {
|
Some(stream) => {
|
||||||
stream.async_send(data);
|
stream.async_send(data);
|
||||||
|
3
rust-lib/flowy-sdk/src/module.rs
Normal file
3
rust-lib/flowy-sdk/src/module.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
use flowy_sys::prelude::Module;
|
||||||
|
|
||||||
|
pub fn build_modules() -> Vec<Module> { vec![flowy_user::module::create()] }
|
85
rust-lib/flowy-sdk/tests/sdk/helper.rs
Normal file
85
rust-lib/flowy-sdk/tests/sdk/helper.rs
Normal file
@ -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
rust-lib/flowy-sdk/tests/sdk/main.rs
Normal file
2
rust-lib/flowy-sdk/tests/sdk/main.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
mod helper;
|
||||||
|
mod user_check;
|
26
rust-lib/flowy-sdk/tests/sdk/user_check.rs
Normal file
26
rust-lib/flowy-sdk/tests/sdk/user_check.rs
Normal file
@ -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(), "helloworld@gmail.com".to_owned());
|
||||||
|
|
||||||
|
FlowySDKTester::new(AuthCheck)
|
||||||
|
.bytes_payload(user_data)
|
||||||
|
.callback(callback)
|
||||||
|
.run();
|
||||||
|
}
|
@ -21,6 +21,7 @@ serde_with = "1.9.4"
|
|||||||
thread-id = "3.3.0"
|
thread-id = "3.3.0"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
dyn-clone = "1.0"
|
dyn-clone = "1.0"
|
||||||
|
derivative = "2.2.0"
|
||||||
|
|
||||||
#optional crate
|
#optional crate
|
||||||
bincode = { version = "1.3", optional = true}
|
bincode = { version = "1.3", optional = true}
|
||||||
|
@ -7,7 +7,7 @@ use std::{fmt, option::NoneError};
|
|||||||
use tokio::sync::mpsc::error::SendError;
|
use tokio::sync::mpsc::error::SendError;
|
||||||
|
|
||||||
#[cfg(feature = "use_serde")]
|
#[cfg(feature = "use_serde")]
|
||||||
use serde::{Deserialize, Serialize, Serializer};
|
use serde::{Serialize, Serializer};
|
||||||
|
|
||||||
pub trait Error: fmt::Debug + fmt::Display + DynClone {
|
pub trait Error: fmt::Debug + fmt::Display + DynClone {
|
||||||
fn status_code(&self) -> StatusCode;
|
fn status_code(&self) -> StatusCode;
|
||||||
@ -18,7 +18,11 @@ pub trait Error: fmt::Debug + fmt::Display + DynClone {
|
|||||||
dyn_clone::clone_trait_object!(Error);
|
dyn_clone::clone_trait_object!(Error);
|
||||||
|
|
||||||
impl<T: Error + 'static> From<T> for SystemError {
|
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)]
|
#[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 {
|
impl From<SystemError> for EventResponse {
|
||||||
fn from(err: SystemError) -> Self { err.inner_error().as_response() }
|
fn from(err: SystemError) -> Self { err.inner_error().as_response() }
|
||||||
}
|
}
|
||||||
@ -95,7 +103,14 @@ where
|
|||||||
{
|
{
|
||||||
fn status_code(&self) -> StatusCode { StatusCode::Err }
|
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")]
|
#[cfg(feature = "use_serde")]
|
||||||
|
@ -1,8 +1,3 @@
|
|||||||
use std::pin::Pin;
|
|
||||||
|
|
||||||
use bytes::Bytes;
|
|
||||||
use futures::Stream;
|
|
||||||
|
|
||||||
pub enum PayloadError {}
|
pub enum PayloadError {}
|
||||||
|
|
||||||
// TODO: support stream data
|
// TODO: support stream data
|
||||||
|
@ -3,14 +3,14 @@ use std::future::Future;
|
|||||||
use crate::{
|
use crate::{
|
||||||
error::{InternalError, SystemError},
|
error::{InternalError, SystemError},
|
||||||
module::Event,
|
module::Event,
|
||||||
request::{payload::Payload, PayloadError},
|
request::payload::Payload,
|
||||||
response::Responder,
|
response::Responder,
|
||||||
util::ready::{ready, Ready},
|
util::ready::{ready, Ready},
|
||||||
};
|
};
|
||||||
use bytes::Bytes;
|
|
||||||
use futures_core::{ready, Stream};
|
use futures_core::ready;
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{Debug, Display},
|
fmt::Debug,
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
ops,
|
ops,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
@ -57,13 +57,19 @@ impl FromRequest for String {
|
|||||||
|
|
||||||
fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future {
|
fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future {
|
||||||
match &payload {
|
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())),
|
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)]
|
#[doc(hidden)]
|
||||||
impl<T> FromRequest for Result<T, T::Error>
|
impl<T> FromRequest for Result<T, T::Error>
|
||||||
@ -126,7 +132,7 @@ where
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future {
|
fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future {
|
||||||
match payload {
|
match payload {
|
||||||
Payload::None => ready(Err(unexpected_none_payload())),
|
Payload::None => ready(Err(unexpected_none_payload(req))),
|
||||||
Payload::Bytes(bytes) => {
|
Payload::Bytes(bytes) => {
|
||||||
let data: T = bincode::deserialize(bytes).unwrap();
|
let data: T = bincode::deserialize(bytes).unwrap();
|
||||||
ready(Ok(In(data)))
|
ready(Ok(In(data)))
|
||||||
@ -146,7 +152,7 @@ where
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future {
|
fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future {
|
||||||
match payload {
|
match payload {
|
||||||
Payload::None => ready(Err(unexpected_none_payload())),
|
Payload::None => ready(Err(unexpected_none_payload(req))),
|
||||||
Payload::Bytes(bytes) => {
|
Payload::Bytes(bytes) => {
|
||||||
let data: T = ::protobuf::Message::parse_from_bytes(bytes).unwrap();
|
let data: T = ::protobuf::Message::parse_from_bytes(bytes).unwrap();
|
||||||
ready(Ok(In(data)))
|
ready(Ok(In(data)))
|
||||||
|
@ -30,8 +30,8 @@ impl EventResponseBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error(mut self, error: Option<SystemError>) -> Self {
|
pub fn error(mut self, error: SystemError) -> Self {
|
||||||
self.error = error;
|
self.error = Some(error);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,9 @@ pub trait Responder {
|
|||||||
macro_rules! impl_responder {
|
macro_rules! impl_responder {
|
||||||
($res: ty) => {
|
($res: ty) => {
|
||||||
impl Responder for $res {
|
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")]
|
#[cfg(feature = "use_protobuf")]
|
||||||
impl<T> Responder for Out<T>
|
impl<T> Responder for Out<T>
|
||||||
where
|
where
|
||||||
@ -73,3 +83,11 @@ where
|
|||||||
EventResponseBuilder::Ok().data(bytes).build()
|
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) }
|
||||||
|
}
|
||||||
|
@ -8,11 +8,11 @@ use crate::{
|
|||||||
use serde::{Deserialize, Serialize, Serializer};
|
use serde::{Deserialize, Serialize, Serializer};
|
||||||
use std::{fmt, fmt::Formatter};
|
use std::{fmt, fmt::Formatter};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
|
||||||
pub enum StatusCode {
|
pub enum StatusCode {
|
||||||
Ok,
|
Ok = 0,
|
||||||
Err,
|
Err = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
// serde user guide: https://serde.rs/field-attrs.html
|
// serde user guide: https://serde.rs/field-attrs.html
|
||||||
|
@ -1,71 +1,99 @@
|
|||||||
use crate::{
|
use crate::{module::Event, request::Payload, response::EventResponse};
|
||||||
module::{Event, ModuleRequest},
|
use derivative::*;
|
||||||
request::{EventRequest, Payload},
|
|
||||||
response::EventResponse,
|
|
||||||
};
|
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{Debug, Display},
|
fmt::{Debug, Display},
|
||||||
hash::Hash,
|
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 type BoxStreamCallback<T> = Box<dyn FnOnce(T, EventResponse) + 'static + Send + Sync>;
|
||||||
pub struct SenderPayload {
|
|
||||||
pub(crate) payload: Payload,
|
// #[derive(Debug)]
|
||||||
pub(crate) event: Event,
|
// 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>,
|
||||||
|
// }
|
||||||
|
|
||||||
|
#[derive(Derivative)]
|
||||||
|
#[derivative(Debug)]
|
||||||
|
pub struct SenderRequest<T>
|
||||||
|
where
|
||||||
|
T: 'static + Debug,
|
||||||
|
{
|
||||||
|
pub config: T,
|
||||||
|
pub event: Event,
|
||||||
|
pub payload: Option<Payload>,
|
||||||
|
#[derivative(Debug = "ignore")]
|
||||||
|
pub callback: Option<BoxStreamCallback<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SenderPayload {
|
impl<T> SenderRequest<T>
|
||||||
pub fn new<E>(event: E) -> SenderPayload
|
where
|
||||||
|
T: 'static + Debug,
|
||||||
|
{
|
||||||
|
pub fn new<E>(config: T, event: E) -> Self
|
||||||
where
|
where
|
||||||
E: Eq + Hash + Debug + Clone + Display,
|
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!() }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type BoxStreamCallback<T> = Box<dyn FnOnce(T, EventResponse) + 'static + Send + Sync>;
|
|
||||||
pub struct SenderData<T>
|
|
||||||
where
|
|
||||||
T: 'static,
|
|
||||||
{
|
|
||||||
pub config: T,
|
|
||||||
pub payload: SenderPayload,
|
|
||||||
pub callback: Option<BoxStreamCallback<T>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> SenderData<T> {
|
|
||||||
pub fn new(config: T, payload: SenderPayload) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
config,
|
config,
|
||||||
payload,
|
payload: None,
|
||||||
|
event: event.into(),
|
||||||
callback: None,
|
callback: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn callback(mut self, callback: BoxStreamCallback<T>) -> Self {
|
pub fn payload(mut self, payload: Payload) -> Self {
|
||||||
self.callback = Some(callback);
|
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
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error::{InternalError, SystemError},
|
error::{InternalError, SystemError},
|
||||||
module::{Event, ModuleRequest},
|
module::ModuleRequest,
|
||||||
request::{EventRequest, Payload},
|
request::{EventRequest, Payload},
|
||||||
response::EventResponse,
|
response::EventResponse,
|
||||||
sender::{SenderData, SenderPayload},
|
sender::SenderRequest,
|
||||||
service::{BoxService, Service, ServiceFactory},
|
service::{BoxService, Service, ServiceFactory},
|
||||||
system::ModuleMap,
|
system::ModuleMap,
|
||||||
};
|
};
|
||||||
use futures_core::{future::LocalBoxFuture, ready, task::Context};
|
use futures_core::{future::LocalBoxFuture, ready, task::Context};
|
||||||
use std::future::Future;
|
use std::{fmt::Debug, future::Future};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
macros::support::{Pin, Poll},
|
macros::support::{Pin, Poll},
|
||||||
sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
|
sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
|
||||||
@ -17,13 +17,13 @@ use tokio::{
|
|||||||
macro_rules! service_factor_impl {
|
macro_rules! service_factor_impl {
|
||||||
($name:ident) => {
|
($name:ident) => {
|
||||||
#[allow(non_snake_case, missing_docs)]
|
#[allow(non_snake_case, missing_docs)]
|
||||||
impl<T> ServiceFactory<SenderData<T>> for $name<T>
|
impl<T> ServiceFactory<SenderRequest<T>> for $name<T>
|
||||||
where
|
where
|
||||||
T: 'static,
|
T: 'static + Debug,
|
||||||
{
|
{
|
||||||
type Response = EventResponse;
|
type Response = EventResponse;
|
||||||
type Error = SystemError;
|
type Error = SystemError;
|
||||||
type Service = BoxService<SenderData<T>, Self::Response, Self::Error>;
|
type Service = BoxService<SenderRequest<T>, Self::Response, Self::Error>;
|
||||||
type Context = ();
|
type Context = ();
|
||||||
type Future = LocalBoxFuture<'static, Result<Self::Service, Self::Error>>;
|
type Future = LocalBoxFuture<'static, Result<Self::Service, Self::Error>>;
|
||||||
|
|
||||||
@ -40,24 +40,27 @@ struct SenderService {
|
|||||||
module_map: ModuleMap,
|
module_map: ModuleMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Service<SenderData<T>> for SenderService
|
impl<T> Service<SenderRequest<T>> for SenderService
|
||||||
where
|
where
|
||||||
T: 'static,
|
T: 'static + Debug,
|
||||||
{
|
{
|
||||||
type Response = EventResponse;
|
type Response = EventResponse;
|
||||||
type Error = SystemError;
|
type Error = SystemError;
|
||||||
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
|
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 module_map = self.module_map.clone();
|
||||||
let SenderData {
|
let SenderRequest {
|
||||||
config,
|
config,
|
||||||
|
event,
|
||||||
payload,
|
payload,
|
||||||
callback,
|
callback,
|
||||||
} = data;
|
} = data;
|
||||||
|
|
||||||
let event = payload.event.clone();
|
let mut request = ModuleRequest::new(event.clone());
|
||||||
let request = payload.into();
|
if let Some(payload) = payload {
|
||||||
|
request = request.payload(payload);
|
||||||
|
}
|
||||||
|
|
||||||
let fut = async move {
|
let fut = async move {
|
||||||
let result = {
|
let result = {
|
||||||
@ -87,21 +90,21 @@ where
|
|||||||
|
|
||||||
pub struct Sender<T>
|
pub struct Sender<T>
|
||||||
where
|
where
|
||||||
T: 'static,
|
T: 'static + Debug,
|
||||||
{
|
{
|
||||||
module_map: ModuleMap,
|
module_map: ModuleMap,
|
||||||
data_tx: UnboundedSender<SenderData<T>>,
|
data_tx: UnboundedSender<SenderRequest<T>>,
|
||||||
data_rx: Option<UnboundedReceiver<SenderData<T>>>,
|
data_rx: Option<UnboundedReceiver<SenderRequest<T>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
service_factor_impl!(Sender);
|
service_factor_impl!(Sender);
|
||||||
|
|
||||||
impl<T> Sender<T>
|
impl<T> Sender<T>
|
||||||
where
|
where
|
||||||
T: 'static,
|
T: 'static + Debug,
|
||||||
{
|
{
|
||||||
pub fn new(module_map: ModuleMap) -> Self {
|
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 {
|
Self {
|
||||||
module_map,
|
module_map,
|
||||||
data_tx,
|
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(());
|
let factory = self.new_service(());
|
||||||
|
|
||||||
futures::executor::block_on(async {
|
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>
|
pub struct SenderRunner<T>
|
||||||
where
|
where
|
||||||
T: 'static,
|
T: 'static + Debug,
|
||||||
{
|
{
|
||||||
module_map: ModuleMap,
|
module_map: ModuleMap,
|
||||||
data_rx: UnboundedReceiver<SenderData<T>>,
|
data_rx: UnboundedReceiver<SenderRequest<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
service_factor_impl!(SenderRunner);
|
service_factor_impl!(SenderRunner);
|
||||||
|
|
||||||
impl<T> SenderRunner<T>
|
impl<T> SenderRunner<T>
|
||||||
where
|
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 }
|
Self { module_map, data_rx }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Future for SenderRunner<T>
|
impl<T> Future for SenderRunner<T>
|
||||||
where
|
where
|
||||||
T: 'static,
|
T: 'static + Debug,
|
||||||
{
|
{
|
||||||
type Output = ();
|
type Output = ();
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
@ -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};
|
use std::{cell::RefCell, sync::Once};
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -10,24 +10,18 @@ pub fn setup_env() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ExecutorAction {
|
|
||||||
command: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FlowySystemExecutor {}
|
|
||||||
|
|
||||||
thread_local!(
|
thread_local!(
|
||||||
static SENDER: RefCell<Option<Sender<i64>>> = RefCell::new(None);
|
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() {
|
SENDER.with(|cell| match &*cell.borrow() {
|
||||||
Some(stream) => stream.sync_send(data),
|
Some(stream) => stream.sync_send(data),
|
||||||
None => panic!(""),
|
None => panic!(""),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn async_send(data: SenderData<i64>) {
|
pub fn async_send(data: SenderRequest<i64>) {
|
||||||
SENDER.with(|cell| match &*cell.borrow() {
|
SENDER.with(|cell| match &*cell.borrow() {
|
||||||
Some(stream) => {
|
Some(stream) => {
|
||||||
stream.async_send(data);
|
stream.async_send(data);
|
||||||
|
@ -10,15 +10,12 @@ fn test_init() {
|
|||||||
let modules = vec![Module::new().event(event, hello)];
|
let modules = vec![Module::new().event(event, hello)];
|
||||||
|
|
||||||
init_system(modules, move || {
|
init_system(modules, move || {
|
||||||
let payload = SenderPayload::new(event);
|
let request = SenderRequest::new(1, event).callback(|_config, response| {
|
||||||
|
|
||||||
let stream_data = SenderData::new(1, payload).callback(Box::new(|_config, response| {
|
|
||||||
log::info!("async resp: {:?}", response);
|
log::info!("async resp: {:?}", response);
|
||||||
}));
|
});
|
||||||
|
|
||||||
let resp = sync_send(stream_data);
|
let resp = sync_send(request);
|
||||||
log::info!("sync resp: {:?}", resp);
|
log::info!("sync resp: {:?}", resp);
|
||||||
|
|
||||||
stop_system();
|
stop_system();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ serde = { version = "1.0", features = ["derive"] }
|
|||||||
validator = "0.12.0"
|
validator = "0.12.0"
|
||||||
rand = { version = "0.8", features=["std_rng"] }
|
rand = { version = "0.8", features=["std_rng"] }
|
||||||
unicode-segmentation = "1.7.1"
|
unicode-segmentation = "1.7.1"
|
||||||
|
log = "0.4.14"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
quickcheck = "0.9.2"
|
quickcheck = "0.9.2"
|
||||||
|
@ -4,7 +4,10 @@ use derive_more::Display;
|
|||||||
pub enum UserEvent {
|
pub enum UserEvent {
|
||||||
#[display(fmt = "AuthCheck")]
|
#[display(fmt = "AuthCheck")]
|
||||||
AuthCheck = 0,
|
AuthCheck = 0,
|
||||||
|
#[display(fmt = "SignIn")]
|
||||||
SignIn = 1,
|
SignIn = 1,
|
||||||
|
#[display(fmt = "SignUp")]
|
||||||
SignUp = 2,
|
SignUp = 2,
|
||||||
|
#[display(fmt = "SignOut")]
|
||||||
SignOut = 3,
|
SignOut = 3,
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,16 @@ use std::convert::TryInto;
|
|||||||
name = %data.name
|
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)]
|
#[derive(Debug, serde::Deserialize, serde::Serialize)]
|
||||||
pub struct UserData {
|
pub struct UserData {
|
||||||
@ -20,6 +29,10 @@ pub struct UserData {
|
|||||||
email: String,
|
email: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl UserData {
|
||||||
|
pub fn new(name: String, email: String) -> Self { Self { name, email } }
|
||||||
|
}
|
||||||
|
|
||||||
impl TryInto<User> for UserData {
|
impl TryInto<User> for UserData {
|
||||||
type Error = String;
|
type Error = String;
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
mod auth;
|
pub mod auth;
|
||||||
|
|
||||||
pub use auth::*;
|
pub use auth::*;
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
mod domain;
|
mod domain;
|
||||||
mod error;
|
mod error;
|
||||||
mod event;
|
pub mod event;
|
||||||
mod handlers;
|
mod handlers;
|
||||||
pub mod module;
|
pub mod module;
|
||||||
|
|
||||||
|
pub mod prelude {
|
||||||
|
pub use crate::{
|
||||||
|
domain::*,
|
||||||
|
event::{UserEvent::*, *},
|
||||||
|
handlers::auth::*,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# https://rust-lang.github.io/rustfmt/?version=master&search=
|
# https://rust-lang.github.io/rustfmt/?version=master&search=
|
||||||
max_width = 120
|
max_width = 100
|
||||||
tab_spaces = 4
|
tab_spaces = 4
|
||||||
fn_single_line = true
|
fn_single_line = true
|
||||||
match_block_trailing_comma = true
|
match_block_trailing_comma = true
|
||||||
|
Loading…
Reference in New Issue
Block a user