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-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" />
|
||||
|
@ -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 {
|
||||
|
@ -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 stream_data = SenderData::new(port, payload).callback(Box::new(|_config, response| {
|
||||
log::info!("async resp: {:?}", response);
|
||||
}));
|
||||
let mut request = SenderRequest::new(port, event).callback(|_, resp| {
|
||||
log::info!("async resp: {:?}", resp);
|
||||
});
|
||||
|
||||
async_send(stream_data);
|
||||
if !payload.is_empty() {
|
||||
request = request.payload(Payload::Bytes(bytes));
|
||||
}
|
||||
|
||||
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]
|
||||
|
@ -8,3 +8,14 @@ edition = "2018"
|
||||
[dependencies]
|
||||
flowy-sys = { path = "../flowy-sys" }
|
||||
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::*;
|
||||
use std::cell::RefCell;
|
||||
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();
|
||||
|
||||
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> {
|
||||
let modules = vec![];
|
||||
modules
|
||||
}
|
||||
|
||||
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
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"
|
||||
lazy_static = "1.4.0"
|
||||
dyn-clone = "1.0"
|
||||
derivative = "2.2.0"
|
||||
|
||||
#optional crate
|
||||
bincode = { version = "1.3", optional = true}
|
||||
|
@ -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")]
|
||||
|
@ -1,8 +1,3 @@
|
||||
use std::pin::Pin;
|
||||
|
||||
use bytes::Bytes;
|
||||
use futures::Stream;
|
||||
|
||||
pub enum PayloadError {}
|
||||
|
||||
// TODO: support stream data
|
||||
|
@ -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)))
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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) }
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
pub type BoxStreamCallback<T> = Box<dyn FnOnce(T, EventResponse) + 'static + Send + Sync>;
|
||||
|
||||
// #[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>,
|
||||
// }
|
||||
|
||||
#[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 {
|
||||
pub fn new<E>(event: E) -> SenderPayload
|
||||
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 {
|
||||
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 {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -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> {
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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,3 +1,3 @@
|
||||
mod auth;
|
||||
pub mod auth;
|
||||
|
||||
pub use auth::*;
|
||||
|
@ -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,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
|
||||
|
Loading…
Reference in New Issue
Block a user