mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
generice handle input params using In<> and Out<>, support protobuf with features=user_protobuf
This commit is contained in:
parent
9371a3d31e
commit
f73b3ded1d
@ -16,9 +16,9 @@ pub extern "C" fn init_sdk(path: *mut c_char) -> i64 {
|
||||
#[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 request = EventRequest::from_data(bytes);
|
||||
let payload = SenderPayload::from_data(bytes);
|
||||
|
||||
let stream_data = CommandData::new(port, Some(request)).with_callback(Box::new(|_config, response| {
|
||||
let stream_data = SenderData::new(port, payload).callback(Box::new(|_config, response| {
|
||||
log::info!("async resp: {:?}", response);
|
||||
}));
|
||||
|
||||
|
@ -18,15 +18,13 @@ pub fn init_modules() -> Vec<Module> {
|
||||
pub fn init_system<F>(modules: Vec<Module>) {
|
||||
FlowySystem::construct(
|
||||
|| modules,
|
||||
|module_map| {
|
||||
let mut stream = CommandSender::<i64>::new(module_map.clone());
|
||||
let runner = CommandSenderRunner::new(module_map, stream.take_data_rx());
|
||||
|module_map, runtime| {
|
||||
let mut sender = Sender::<i64>::new(module_map.clone());
|
||||
runtime.spawn(SenderRunner::new(module_map, sender.take_rx()));
|
||||
|
||||
CMD_SENDER.with(|cell| {
|
||||
*cell.borrow_mut() = Some(stream);
|
||||
SENDER.with(|cell| {
|
||||
*cell.borrow_mut() = Some(sender);
|
||||
});
|
||||
|
||||
runner
|
||||
},
|
||||
)
|
||||
.run()
|
||||
@ -34,18 +32,18 @@ pub fn init_system<F>(modules: Vec<Module>) {
|
||||
}
|
||||
|
||||
thread_local!(
|
||||
static CMD_SENDER: RefCell<Option<CommandSender<i64>>> = RefCell::new(None);
|
||||
static SENDER: RefCell<Option<Sender<i64>>> = RefCell::new(None);
|
||||
);
|
||||
|
||||
pub fn sync_send(data: CommandData<i64>) -> EventResponse {
|
||||
CMD_SENDER.with(|cell| match &*cell.borrow() {
|
||||
pub fn sync_send(data: SenderData<i64>) -> EventResponse {
|
||||
SENDER.with(|cell| match &*cell.borrow() {
|
||||
Some(stream) => stream.sync_send(data),
|
||||
None => panic!(""),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn async_send(data: CommandData<i64>) {
|
||||
CMD_SENDER.with(|cell| match &*cell.borrow() {
|
||||
pub fn async_send(data: SenderData<i64>) {
|
||||
SENDER.with(|cell| match &*cell.borrow() {
|
||||
Some(stream) => {
|
||||
stream.async_send(data);
|
||||
},
|
||||
|
@ -26,6 +26,7 @@ dyn-clone = "1.0"
|
||||
bincode = { version = "1.3", optional = true}
|
||||
serde = { version = "1.0", features = ["derive"], optional = true }
|
||||
serde_json = {version = "1.0", optional = true}
|
||||
protobuf = {version = "2.24.1", optional = true}
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
@ -33,3 +34,4 @@ futures-util = "0.3.15"
|
||||
|
||||
[features]
|
||||
use_serde = ["bincode", "serde", "serde_json"]
|
||||
use_protobuf= ["protobuf"]
|
||||
|
@ -1 +0,0 @@
|
||||
pub mod container;
|
@ -1,6 +1,5 @@
|
||||
#![feature(try_trait)]
|
||||
|
||||
mod data;
|
||||
mod error;
|
||||
mod module;
|
||||
mod request;
|
||||
@ -9,11 +8,9 @@ mod rt;
|
||||
mod service;
|
||||
mod util;
|
||||
|
||||
#[cfg(feature = "dart_ffi")]
|
||||
pub mod dart_ffi;
|
||||
mod stream;
|
||||
mod sender;
|
||||
mod system;
|
||||
|
||||
pub mod prelude {
|
||||
pub use crate::{error::*, module::*, request::*, response::*, rt::*, stream::*};
|
||||
pub use crate::{error::*, module::*, request::*, response::*, rt::*, sender::*};
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
mod data;
|
||||
mod module;
|
||||
|
||||
pub use container::*;
|
||||
pub use data::*;
|
||||
pub use module::*;
|
||||
|
||||
mod container;
|
||||
mod data;
|
||||
mod module;
|
||||
|
@ -1,20 +1,3 @@
|
||||
use crate::{
|
||||
data::container::DataContainer,
|
||||
error::SystemError,
|
||||
module::ModuleData,
|
||||
request::FromRequest,
|
||||
response::Responder,
|
||||
service::{BoxService, Handler, Service, ServiceFactory, ServiceRequest, ServiceResponse},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
error::InternalError,
|
||||
request::{payload::Payload, EventRequest},
|
||||
response::EventResponse,
|
||||
service::{factory, BoxServiceFactory, HandlerService},
|
||||
};
|
||||
use futures_core::{future::LocalBoxFuture, ready};
|
||||
use pin_project::pin_project;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt::{Debug, Display},
|
||||
@ -24,8 +7,29 @@ use std::{
|
||||
rc::Rc,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use futures_core::{future::LocalBoxFuture, ready};
|
||||
use pin_project::pin_project;
|
||||
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
|
||||
|
||||
use crate::{
|
||||
error::{InternalError, SystemError},
|
||||
module::{container::DataContainer, ModuleData},
|
||||
request::{payload::Payload, EventRequest, FromRequest},
|
||||
response::{EventResponse, Responder},
|
||||
service::{
|
||||
factory,
|
||||
BoxService,
|
||||
BoxServiceFactory,
|
||||
Handler,
|
||||
HandlerService,
|
||||
Service,
|
||||
ServiceFactory,
|
||||
ServiceRequest,
|
||||
ServiceResponse,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
|
||||
pub struct Event(String);
|
||||
|
||||
@ -39,13 +43,13 @@ pub struct Module {
|
||||
name: String,
|
||||
data: DataContainer,
|
||||
service_map: Rc<HashMap<Event, EventServiceFactory>>,
|
||||
req_tx: UnboundedSender<EventRequest>,
|
||||
req_rx: UnboundedReceiver<EventRequest>,
|
||||
req_tx: UnboundedSender<ModuleRequest>,
|
||||
req_rx: UnboundedReceiver<ModuleRequest>,
|
||||
}
|
||||
|
||||
impl Module {
|
||||
pub fn new() -> Self {
|
||||
let (req_tx, req_rx) = unbounded_channel::<EventRequest>();
|
||||
let (req_tx, req_rx) = unbounded_channel::<ModuleRequest>();
|
||||
Self {
|
||||
name: "".to_owned(),
|
||||
data: DataContainer::new(),
|
||||
@ -84,22 +88,10 @@ impl Module {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn req_tx(&self) -> UnboundedSender<EventRequest> { self.req_tx.clone() }
|
||||
|
||||
pub fn handle(&self, request: EventRequest) {
|
||||
log::debug!("Module: {} receive request: {:?}", self.name, request);
|
||||
match self.req_tx.send(request) {
|
||||
Ok(_) => {},
|
||||
Err(e) => {
|
||||
log::error!("Module: {} with error: {:?}", self.name, e);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn forward_map(&self) -> HashMap<Event, UnboundedSender<EventRequest>> {
|
||||
pub fn forward_map(&self) -> HashMap<Event, UnboundedSender<ModuleRequest>> {
|
||||
self.service_map
|
||||
.keys()
|
||||
.map(|key| (key.clone(), self.req_tx()))
|
||||
.map(|key| (key.clone(), self.req_tx.clone()))
|
||||
.collect::<HashMap<_, _>>()
|
||||
}
|
||||
|
||||
@ -113,9 +105,9 @@ impl Future for Module {
|
||||
match ready!(Pin::new(&mut self.req_rx).poll_recv(cx)) {
|
||||
None => return Poll::Ready(()),
|
||||
Some(request) => {
|
||||
let mut service = self.new_service(request.get_id().to_string());
|
||||
let mut service = self.new_service(());
|
||||
if let Ok(service) = ready!(Pin::new(&mut service).poll(cx)) {
|
||||
log::trace!("Spawn module service for request {}", request.get_id());
|
||||
log::trace!("Spawn module service for request {}", request.id());
|
||||
tokio::task::spawn_local(async move {
|
||||
let _ = service.call(request).await;
|
||||
});
|
||||
@ -126,15 +118,45 @@ impl Future for Module {
|
||||
}
|
||||
}
|
||||
|
||||
impl ServiceFactory<EventRequest> for Module {
|
||||
#[derive(Debug)]
|
||||
pub struct ModuleRequest {
|
||||
inner: EventRequest,
|
||||
payload: Payload,
|
||||
}
|
||||
|
||||
impl ModuleRequest {
|
||||
pub fn new<E>(event: E) -> Self
|
||||
where
|
||||
E: Into<Event>,
|
||||
{
|
||||
Self {
|
||||
inner: EventRequest::new(event),
|
||||
payload: Payload::None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn payload(mut self, payload: Payload) -> Self {
|
||||
self.payload = payload;
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn into_parts(self) -> (EventRequest, Payload) { (self.inner, self.payload) }
|
||||
|
||||
pub(crate) fn into_service_request(self) -> ServiceRequest { ServiceRequest::new(self.inner, self.payload) }
|
||||
|
||||
pub(crate) fn id(&self) -> &str { &self.inner.id }
|
||||
|
||||
pub(crate) fn event(&self) -> &Event { &self.inner.event }
|
||||
}
|
||||
|
||||
impl ServiceFactory<ModuleRequest> for Module {
|
||||
type Response = EventResponse;
|
||||
type Error = SystemError;
|
||||
type Service = BoxService<EventRequest, Self::Response, Self::Error>;
|
||||
type Config = String;
|
||||
type Service = BoxService<ModuleRequest, Self::Response, Self::Error>;
|
||||
type Context = ();
|
||||
type Future = LocalBoxFuture<'static, Result<Self::Service, Self::Error>>;
|
||||
|
||||
fn new_service(&self, cfg: Self::Config) -> Self::Future {
|
||||
log::trace!("Create module service for request {}", cfg);
|
||||
fn new_service(&self, cfg: Self::Context) -> Self::Future {
|
||||
let service_map = self.service_map.clone();
|
||||
Box::pin(async move {
|
||||
let service = ModuleService { service_map };
|
||||
@ -148,18 +170,22 @@ pub struct ModuleService {
|
||||
service_map: Rc<HashMap<Event, EventServiceFactory>>,
|
||||
}
|
||||
|
||||
impl Service<EventRequest> for ModuleService {
|
||||
impl Service<ModuleRequest> for ModuleService {
|
||||
type Response = EventResponse;
|
||||
type Error = SystemError;
|
||||
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
|
||||
|
||||
fn call(&self, request: EventRequest) -> Self::Future {
|
||||
log::trace!("Call module service for request {}", request.get_id());
|
||||
match self.service_map.get(request.get_event()) {
|
||||
fn call(&self, request: ModuleRequest) -> Self::Future {
|
||||
log::trace!("Call module service for request {}", &request.id());
|
||||
match self.service_map.get(&request.event()) {
|
||||
Some(factory) => {
|
||||
let service_fut = factory.new_service(());
|
||||
let fut = ModuleServiceFuture {
|
||||
request,
|
||||
fut: factory.new_service(()),
|
||||
fut: Box::pin(async {
|
||||
let service = service_fut.await?;
|
||||
let request = request.into_service_request();
|
||||
service.call(request).await
|
||||
}),
|
||||
};
|
||||
Box::pin(async move { Ok(fut.await.unwrap_or_else(|e| e.into())) })
|
||||
},
|
||||
@ -168,13 +194,13 @@ impl Service<EventRequest> for ModuleService {
|
||||
}
|
||||
}
|
||||
|
||||
type BoxModuleService = BoxService<ServiceRequest, ServiceResponse, SystemError>;
|
||||
// type BoxModuleService = BoxService<ServiceRequest, ServiceResponse,
|
||||
// SystemError>;
|
||||
|
||||
#[pin_project]
|
||||
pub struct ModuleServiceFuture {
|
||||
request: EventRequest,
|
||||
#[pin]
|
||||
fut: LocalBoxFuture<'static, Result<BoxModuleService, SystemError>>,
|
||||
fut: LocalBoxFuture<'static, Result<ServiceResponse, SystemError>>,
|
||||
}
|
||||
|
||||
impl Future for ModuleServiceFuture {
|
||||
@ -182,11 +208,8 @@ impl Future for ModuleServiceFuture {
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
loop {
|
||||
let service = ready!(self.as_mut().project().fut.poll(cx))?;
|
||||
let req = ServiceRequest::new(self.as_mut().request.clone(), Payload::None);
|
||||
log::debug!("Call service to handle request {:?}", self.request);
|
||||
let (_, resp) = ready!(Pin::new(&mut service.call(req)).poll(cx))?.into_parts();
|
||||
return Poll::Ready(Ok(resp));
|
||||
let (_, response) = ready!(self.as_mut().project().fut.poll(cx))?.into_parts();
|
||||
return Poll::Ready(Ok(response));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,9 @@ use futures::Stream;
|
||||
|
||||
pub enum PayloadError {}
|
||||
|
||||
pub type PayloadStream = Pin<Box<dyn Stream<Item = Result<Bytes, PayloadError>>>>;
|
||||
pub enum Payload<S = PayloadStream> {
|
||||
// TODO: support stream data
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Payload {
|
||||
None,
|
||||
Stream(S),
|
||||
Bytes(Vec<u8>),
|
||||
}
|
||||
|
@ -3,45 +3,36 @@ use std::future::Future;
|
||||
use crate::{
|
||||
error::{InternalError, SystemError},
|
||||
module::Event,
|
||||
request::payload::Payload,
|
||||
request::{payload::Payload, PayloadError},
|
||||
response::Responder,
|
||||
util::ready::{ready, Ready},
|
||||
};
|
||||
use futures_core::ready;
|
||||
use bytes::Bytes;
|
||||
use futures_core::{ready, Stream};
|
||||
use std::{
|
||||
fmt::{Debug, Display},
|
||||
hash::Hash,
|
||||
ops,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct EventRequest {
|
||||
id: String,
|
||||
event: Event,
|
||||
data: Option<Vec<u8>>,
|
||||
pub(crate) id: String,
|
||||
pub(crate) event: Event,
|
||||
}
|
||||
|
||||
impl EventRequest {
|
||||
pub fn new<E>(event: E) -> EventRequest
|
||||
where
|
||||
E: Eq + Hash + Debug + Clone + Display,
|
||||
E: Into<Event>,
|
||||
{
|
||||
Self {
|
||||
id: uuid::Uuid::new_v4().to_string(),
|
||||
event: event.into(),
|
||||
data: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn data(mut self, data: Vec<u8>) -> Self {
|
||||
self.data = Some(data);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn get_event(&self) -> &Event { &self.event }
|
||||
|
||||
pub fn get_id(&self) -> &str { &self.id }
|
||||
|
||||
pub fn from_data(_data: Vec<u8>) -> Self { unimplemented!() }
|
||||
}
|
||||
|
||||
pub trait FromRequest: Sized {
|
||||
@ -64,14 +55,16 @@ impl FromRequest for String {
|
||||
type Error = SystemError;
|
||||
type Future = Ready<Result<Self, Self::Error>>;
|
||||
|
||||
fn from_request(req: &EventRequest, _payload: &mut Payload) -> Self::Future {
|
||||
match &req.data {
|
||||
None => ready(Err(InternalError::new("Expected string but request had data").into())),
|
||||
Some(buf) => ready(Ok(String::from_utf8_lossy(buf).into_owned())),
|
||||
fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future {
|
||||
match &payload {
|
||||
Payload::None => ready(Err(unexpected_none_payload())),
|
||||
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() }
|
||||
|
||||
#[doc(hidden)]
|
||||
impl<T> FromRequest for Result<T, T::Error>
|
||||
where
|
||||
@ -105,3 +98,59 @@ where
|
||||
Poll::Ready(Ok(res))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct In<T>(pub T);
|
||||
|
||||
impl<T> In<T> {
|
||||
pub fn into_inner(self) -> T { self.0 }
|
||||
}
|
||||
|
||||
impl<T> ops::Deref for In<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T { &self.0 }
|
||||
}
|
||||
|
||||
impl<T> ops::DerefMut for In<T> {
|
||||
fn deref_mut(&mut self) -> &mut T { &mut self.0 }
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_serde")]
|
||||
impl<T> FromRequest for In<T>
|
||||
where
|
||||
T: serde::de::DeserializeOwned + 'static,
|
||||
{
|
||||
type Error = SystemError;
|
||||
type Future = Ready<Result<Self, SystemError>>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future {
|
||||
match payload {
|
||||
Payload::None => ready(Err(unexpected_none_payload())),
|
||||
Payload::Bytes(bytes) => {
|
||||
let data: T = bincode::deserialize(bytes).unwrap();
|
||||
ready(Ok(In(data)))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_protobuf")]
|
||||
impl<T> FromRequest for In<T>
|
||||
where
|
||||
T: ::protobuf::Message + 'static,
|
||||
{
|
||||
type Error = SystemError;
|
||||
type Future = Ready<Result<Self, SystemError>>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future {
|
||||
match payload {
|
||||
Payload::None => ready(Err(unexpected_none_payload())),
|
||||
Payload::Bytes(bytes) => {
|
||||
let data: T = ::protobuf::Message::parse_from_bytes(bytes).unwrap();
|
||||
ready(Ok(In(data)))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ use crate::{
|
||||
response::{EventResponse, EventResponseBuilder},
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use std::ops;
|
||||
|
||||
pub trait Responder {
|
||||
fn respond_to(self, req: &EventRequest) -> EventResponse;
|
||||
@ -35,13 +36,40 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// #[cfg(feature = "use_serde")]
|
||||
// impl<T> Responder for T
|
||||
// where
|
||||
// T: serde::Serialize,
|
||||
// {
|
||||
// fn respond_to(self, request: &EventRequest) -> EventResponse {
|
||||
// let bytes = bincode::serialize(&self).unwrap();
|
||||
// EventResponseBuilder::Ok().data(bytes).build()
|
||||
// }
|
||||
// }
|
||||
pub struct Out<T>(pub T);
|
||||
|
||||
impl<T> Out<T> {
|
||||
pub fn into_inner(self) -> T { self.0 }
|
||||
}
|
||||
|
||||
impl<T> ops::Deref for Out<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T { &self.0 }
|
||||
}
|
||||
|
||||
impl<T> ops::DerefMut for Out<T> {
|
||||
fn deref_mut(&mut self) -> &mut T { &mut self.0 }
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_serde")]
|
||||
impl<T> Responder for Out<T>
|
||||
where
|
||||
T: serde::Serialize,
|
||||
{
|
||||
fn respond_to(self, request: &EventRequest) -> EventResponse {
|
||||
let bytes: Vec<u8> = bincode::serialize(&self.0).unwrap();
|
||||
EventResponseBuilder::Ok().data(bytes).build()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_protobuf")]
|
||||
impl<T> Responder for Out<T>
|
||||
where
|
||||
T: ::protobuf::Message,
|
||||
{
|
||||
fn respond_to(self, _request: &EventRequest) -> EventResponse {
|
||||
let bytes: Vec<u8> = self.write_to_bytes().unwrap();
|
||||
EventResponseBuilder::Ok().data(bytes).build()
|
||||
}
|
||||
}
|
||||
|
71
rust-lib/flowy-sys/src/sender/data.rs
Normal file
71
rust-lib/flowy-sys/src/sender/data.rs
Normal file
@ -0,0 +1,71 @@
|
||||
use crate::{
|
||||
module::{Event, ModuleRequest},
|
||||
request::{EventRequest, Payload},
|
||||
response::EventResponse,
|
||||
};
|
||||
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!() }
|
||||
}
|
||||
|
||||
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,
|
||||
callback: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn callback(mut self, callback: BoxStreamCallback<T>) -> Self {
|
||||
self.callback = Some(callback);
|
||||
self
|
||||
}
|
||||
}
|
5
rust-lib/flowy-sys/src/sender/mod.rs
Normal file
5
rust-lib/flowy-sys/src/sender/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
mod data;
|
||||
mod sender;
|
||||
|
||||
pub use data::*;
|
||||
pub use sender::*;
|
@ -1,7 +1,9 @@
|
||||
use crate::{
|
||||
error::{InternalError, SystemError},
|
||||
request::EventRequest,
|
||||
module::{Event, ModuleRequest},
|
||||
request::{EventRequest, Payload},
|
||||
response::EventResponse,
|
||||
sender::{SenderData, SenderPayload},
|
||||
service::{BoxService, Service, ServiceFactory},
|
||||
system::ModuleMap,
|
||||
};
|
||||
@ -15,30 +17,30 @@ use tokio::{
|
||||
macro_rules! service_factor_impl {
|
||||
($name:ident) => {
|
||||
#[allow(non_snake_case, missing_docs)]
|
||||
impl<T> ServiceFactory<CommandData<T>> for $name<T>
|
||||
impl<T> ServiceFactory<SenderData<T>> for $name<T>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
type Response = EventResponse;
|
||||
type Error = SystemError;
|
||||
type Service = BoxService<CommandData<T>, Self::Response, Self::Error>;
|
||||
type Config = ();
|
||||
type Service = BoxService<SenderData<T>, Self::Response, Self::Error>;
|
||||
type Context = ();
|
||||
type Future = LocalBoxFuture<'static, Result<Self::Service, Self::Error>>;
|
||||
|
||||
fn new_service(&self, _cfg: Self::Config) -> Self::Future {
|
||||
fn new_service(&self, _cfg: Self::Context) -> Self::Future {
|
||||
let module_map = self.module_map.clone();
|
||||
let service = Box::new(CommandSenderService { module_map });
|
||||
let service = Box::new(SenderService { module_map });
|
||||
Box::pin(async move { Ok(service as Self::Service) })
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
struct CommandSenderService {
|
||||
struct SenderService {
|
||||
module_map: ModuleMap,
|
||||
}
|
||||
|
||||
impl<T> Service<CommandData<T>> for CommandSenderService
|
||||
impl<T> Service<SenderData<T>> for SenderService
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
@ -46,15 +48,22 @@ where
|
||||
type Error = SystemError;
|
||||
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
|
||||
|
||||
fn call(&self, mut data: CommandData<T>) -> Self::Future {
|
||||
fn call(&self, data: SenderData<T>) -> Self::Future {
|
||||
let module_map = self.module_map.clone();
|
||||
let request = data.request.take().unwrap();
|
||||
let SenderData {
|
||||
config,
|
||||
payload,
|
||||
callback,
|
||||
} = data;
|
||||
|
||||
let event = payload.event.clone();
|
||||
let request = payload.into();
|
||||
|
||||
let fut = async move {
|
||||
let result = {
|
||||
match module_map.get(request.get_event()) {
|
||||
match module_map.get(&event) {
|
||||
Some(module) => {
|
||||
let config = request.get_id().to_owned();
|
||||
let fut = module.new_service(config);
|
||||
let fut = module.new_service(());
|
||||
let service_fut = fut.await?.call(request);
|
||||
service_fut.await
|
||||
},
|
||||
@ -66,8 +75,8 @@ where
|
||||
};
|
||||
|
||||
let response = result.unwrap_or_else(|e| e.into());
|
||||
if let Some(callback) = data.callback {
|
||||
callback(data.config, response.clone());
|
||||
if let Some(callback) = callback {
|
||||
callback(config, response.clone());
|
||||
}
|
||||
|
||||
Ok(response)
|
||||
@ -76,48 +85,23 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub type BoxStreamCallback<T> = Box<dyn FnOnce(T, EventResponse) + 'static + Send + Sync>;
|
||||
pub struct CommandData<T>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
config: T,
|
||||
request: Option<EventRequest>,
|
||||
callback: Option<BoxStreamCallback<T>>,
|
||||
}
|
||||
|
||||
impl<T> CommandData<T> {
|
||||
pub fn new(config: T, request: Option<EventRequest>) -> Self {
|
||||
Self {
|
||||
config,
|
||||
request,
|
||||
callback: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_callback(mut self, callback: BoxStreamCallback<T>) -> Self {
|
||||
self.callback = Some(callback);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CommandSender<T>
|
||||
pub struct Sender<T>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
module_map: ModuleMap,
|
||||
data_tx: UnboundedSender<CommandData<T>>,
|
||||
data_rx: Option<UnboundedReceiver<CommandData<T>>>,
|
||||
data_tx: UnboundedSender<SenderData<T>>,
|
||||
data_rx: Option<UnboundedReceiver<SenderData<T>>>,
|
||||
}
|
||||
|
||||
service_factor_impl!(CommandSender);
|
||||
service_factor_impl!(Sender);
|
||||
|
||||
impl<T> CommandSender<T>
|
||||
impl<T> Sender<T>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
pub fn new(module_map: ModuleMap) -> Self {
|
||||
let (data_tx, data_rx) = unbounded_channel::<CommandData<T>>();
|
||||
let (data_tx, data_rx) = unbounded_channel::<SenderData<T>>();
|
||||
Self {
|
||||
module_map,
|
||||
data_tx,
|
||||
@ -125,9 +109,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn async_send(&self, data: CommandData<T>) { let _ = self.data_tx.send(data); }
|
||||
pub fn async_send(&self, data: SenderData<T>) { let _ = self.data_tx.send(data); }
|
||||
|
||||
pub fn sync_send(&self, data: CommandData<T>) -> EventResponse {
|
||||
pub fn sync_send(&self, data: SenderData<T>) -> EventResponse {
|
||||
let factory = self.new_service(());
|
||||
|
||||
futures::executor::block_on(async {
|
||||
@ -136,31 +120,29 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
pub fn tx(&self) -> UnboundedSender<CommandData<T>> { self.data_tx.clone() }
|
||||
|
||||
pub fn take_data_rx(&mut self) -> UnboundedReceiver<CommandData<T>> { self.data_rx.take().unwrap() }
|
||||
pub fn take_rx(&mut self) -> UnboundedReceiver<SenderData<T>> { self.data_rx.take().unwrap() }
|
||||
}
|
||||
|
||||
pub struct CommandSenderRunner<T>
|
||||
pub struct SenderRunner<T>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
module_map: ModuleMap,
|
||||
data_rx: UnboundedReceiver<CommandData<T>>,
|
||||
data_rx: UnboundedReceiver<SenderData<T>>,
|
||||
}
|
||||
|
||||
service_factor_impl!(CommandSenderRunner);
|
||||
service_factor_impl!(SenderRunner);
|
||||
|
||||
impl<T> CommandSenderRunner<T>
|
||||
impl<T> SenderRunner<T>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
pub fn new(module_map: ModuleMap, data_rx: UnboundedReceiver<CommandData<T>>) -> Self {
|
||||
pub fn new(module_map: ModuleMap, data_rx: UnboundedReceiver<SenderData<T>>) -> Self {
|
||||
Self { module_map, data_rx }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Future for CommandSenderRunner<T>
|
||||
impl<T> Future for SenderRunner<T>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
@ -1,7 +1,7 @@
|
||||
use crate::service::{Service, ServiceFactory};
|
||||
use futures_core::future::LocalBoxFuture;
|
||||
|
||||
pub fn factory<SF, Req>(factory: SF) -> BoxServiceFactory<SF::Config, Req, SF::Response, SF::Error>
|
||||
pub fn factory<SF, Req>(factory: SF) -> BoxServiceFactory<SF::Context, Req, SF::Response, SF::Error>
|
||||
where
|
||||
SF: ServiceFactory<Req> + 'static,
|
||||
Req: 'static,
|
||||
@ -16,7 +16,7 @@ where
|
||||
type Inner<Cfg, Req, Res, Err> = Box<
|
||||
dyn ServiceFactory<
|
||||
Req,
|
||||
Config = Cfg,
|
||||
Context = Cfg,
|
||||
Response = Res,
|
||||
Error = Err,
|
||||
Service = BoxService<Req, Res, Err>,
|
||||
@ -34,7 +34,7 @@ where
|
||||
type Response = Res;
|
||||
type Error = Err;
|
||||
type Service = BoxService<Req, Res, Err>;
|
||||
type Config = Cfg;
|
||||
type Context = Cfg;
|
||||
type Future = LocalBoxFuture<'static, Result<Self::Service, Self::Error>>;
|
||||
|
||||
fn new_service(&self, cfg: Cfg) -> Self::Future { self.0.new_service(cfg) }
|
||||
@ -91,7 +91,7 @@ where
|
||||
Req: 'static,
|
||||
Res: 'static,
|
||||
Err: 'static,
|
||||
SF: ServiceFactory<Req, Config = Cfg, Response = Res, Error = Err>,
|
||||
SF: ServiceFactory<Req, Context = Cfg, Response = Res, Error = Err>,
|
||||
SF::Future: 'static,
|
||||
SF::Service: 'static,
|
||||
<SF::Service as Service<Req>>::Future: 'static,
|
||||
@ -99,7 +99,7 @@ where
|
||||
type Response = Res;
|
||||
type Error = Err;
|
||||
type Service = BoxService<Req, Res, Err>;
|
||||
type Config = Cfg;
|
||||
type Context = Cfg;
|
||||
type Future = LocalBoxFuture<'static, Result<Self::Service, Self::Error>>;
|
||||
|
||||
fn new_service(&self, cfg: Cfg) -> Self::Future {
|
||||
|
@ -75,7 +75,7 @@ where
|
||||
type Response = ServiceResponse;
|
||||
type Error = SystemError;
|
||||
type Service = Self;
|
||||
type Config = ();
|
||||
type Context = ();
|
||||
type Future = Ready<Result<Self::Service, Self::Error>>;
|
||||
|
||||
fn new_service(&self, _: ()) -> Self::Future { ready(Ok(self.clone())) }
|
||||
@ -139,10 +139,10 @@ where
|
||||
};
|
||||
},
|
||||
HandlerServiceProj::Handle(fut, req) => {
|
||||
let res = ready!(fut.poll(cx));
|
||||
let result = ready!(fut.poll(cx));
|
||||
let req = req.take().unwrap();
|
||||
let res = res.respond_to(&req);
|
||||
return Poll::Ready(Ok(ServiceResponse::new(req, res)));
|
||||
let resp = result.respond_to(&req);
|
||||
return Poll::Ready(Ok(ServiceResponse::new(req, resp)));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -17,10 +17,10 @@ pub trait ServiceFactory<Request> {
|
||||
type Response;
|
||||
type Error;
|
||||
type Service: Service<Request, Response = Self::Response, Error = Self::Error>;
|
||||
type Config;
|
||||
type Context;
|
||||
type Future: Future<Output = Result<Self::Service, Self::Error>>;
|
||||
|
||||
fn new_service(&self, cfg: Self::Config) -> Self::Future;
|
||||
fn new_service(&self, cfg: Self::Context) -> Self::Future;
|
||||
}
|
||||
|
||||
pub struct ServiceRequest {
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::{
|
||||
module::{Event, Module},
|
||||
rt::Runtime,
|
||||
stream::CommandSenderRunner,
|
||||
};
|
||||
use futures_core::{ready, task::Context};
|
||||
use std::{cell::RefCell, collections::HashMap, fmt::Debug, future::Future, io, rc::Rc, sync::Arc};
|
||||
@ -28,12 +27,10 @@ pub struct FlowySystem {
|
||||
}
|
||||
|
||||
impl FlowySystem {
|
||||
pub fn construct<F, S, T>(module_factory: F, sender_factory: S) -> SystemRunner
|
||||
pub fn construct<F, S>(module_factory: F, sender_factory: S) -> SystemRunner
|
||||
where
|
||||
// E: Into<Event<E>> + Eq + Hash + Debug + Clone + 'static,
|
||||
F: FnOnce() -> Vec<Module>,
|
||||
S: FnOnce(ModuleMap) -> CommandSenderRunner<T>,
|
||||
T: 'static,
|
||||
S: FnOnce(ModuleMap, &Runtime),
|
||||
{
|
||||
let runtime = Runtime::new().unwrap();
|
||||
let (sys_cmd_tx, sys_cmd_rx) = unbounded_channel::<SystemCommand>();
|
||||
@ -55,8 +52,7 @@ impl FlowySystem {
|
||||
});
|
||||
|
||||
let system = Self { sys_cmd_tx };
|
||||
let sender_runner = sender_factory(Rc::new(module_map));
|
||||
runtime.spawn(sender_runner);
|
||||
sender_factory(Rc::new(module_map), &runtime);
|
||||
|
||||
FlowySystem::set_current(system);
|
||||
let runner = SystemRunner { rt: runtime, stop_rx };
|
||||
|
@ -1,4 +1,4 @@
|
||||
use flowy_sys::prelude::{CommandData, CommandSender, CommandSenderRunner, EventResponse, FlowySystem, Module};
|
||||
use flowy_sys::prelude::{EventResponse, FlowySystem, Module, Sender, SenderData, SenderRunner};
|
||||
use std::{cell::RefCell, sync::Once};
|
||||
|
||||
#[allow(dead_code)]
|
||||
@ -17,18 +17,18 @@ pub struct ExecutorAction {
|
||||
pub struct FlowySystemExecutor {}
|
||||
|
||||
thread_local!(
|
||||
static CMD_SENDER: RefCell<Option<CommandSender<i64>>> = RefCell::new(None);
|
||||
static SENDER: RefCell<Option<Sender<i64>>> = RefCell::new(None);
|
||||
);
|
||||
|
||||
pub fn sync_send(data: CommandData<i64>) -> EventResponse {
|
||||
CMD_SENDER.with(|cell| match &*cell.borrow() {
|
||||
pub fn sync_send(data: SenderData<i64>) -> EventResponse {
|
||||
SENDER.with(|cell| match &*cell.borrow() {
|
||||
Some(stream) => stream.sync_send(data),
|
||||
None => panic!(""),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn async_send(data: CommandData<i64>) {
|
||||
CMD_SENDER.with(|cell| match &*cell.borrow() {
|
||||
pub fn async_send(data: SenderData<i64>) {
|
||||
SENDER.with(|cell| match &*cell.borrow() {
|
||||
Some(stream) => {
|
||||
stream.async_send(data);
|
||||
},
|
||||
@ -42,15 +42,13 @@ where
|
||||
{
|
||||
FlowySystem::construct(
|
||||
|| modules,
|
||||
|module_map| {
|
||||
let mut stream = CommandSender::<i64>::new(module_map.clone());
|
||||
let runner = CommandSenderRunner::new(module_map, stream.take_data_rx());
|
||||
|module_map, runtime| {
|
||||
let mut sender = Sender::<i64>::new(module_map.clone());
|
||||
runtime.spawn(SenderRunner::new(module_map, sender.take_rx()));
|
||||
|
||||
CMD_SENDER.with(|cell| {
|
||||
*cell.borrow_mut() = Some(stream);
|
||||
SENDER.with(|cell| {
|
||||
*cell.borrow_mut() = Some(sender);
|
||||
});
|
||||
|
||||
runner
|
||||
},
|
||||
)
|
||||
.spawn(async { f() })
|
||||
|
@ -10,8 +10,9 @@ fn test_init() {
|
||||
let modules = vec![Module::new().event(event, hello)];
|
||||
|
||||
init_system(modules, move || {
|
||||
let request = EventRequest::new(event);
|
||||
let stream_data = CommandData::new(1, Some(request)).with_callback(Box::new(|_config, response| {
|
||||
let payload = SenderPayload::new(event);
|
||||
|
||||
let stream_data = SenderData::new(1, payload).callback(Box::new(|_config, response| {
|
||||
log::info!("async resp: {:?}", response);
|
||||
}));
|
||||
|
||||
|
@ -7,7 +7,7 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
derive_more = {version = "0.99", features = ["display"]}
|
||||
flowy-sys = { path = "../flowy-sys" }
|
||||
flowy-sys = { path = "../flowy-sys", features = ["use_serde"] }
|
||||
flowy-log = { path = "../flowy-log" }
|
||||
tracing = { version = "0.1", features = ["log"] }
|
||||
bytes = "0.5"
|
||||
|
@ -1,7 +1,20 @@
|
||||
use crate::domain::{User, UserEmail, UserName};
|
||||
use bytes::Bytes;
|
||||
use flowy_sys::prelude::{In, Out};
|
||||
use std::convert::TryInto;
|
||||
|
||||
// tracing instrument 👉🏻 https://docs.rs/tracing/0.1.26/tracing/attr.instrument.html
|
||||
#[tracing::instrument(
|
||||
name = "User check",
|
||||
skip(data),
|
||||
fields(
|
||||
email = %data.email,
|
||||
name = %data.name
|
||||
)
|
||||
)]
|
||||
pub async fn user_check(data: In<UserData>) -> Out<UserData> { panic!("") }
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize)]
|
||||
pub struct UserData {
|
||||
name: String,
|
||||
email: String,
|
||||
@ -16,6 +29,3 @@ impl TryInto<User> for UserData {
|
||||
Ok(User::new(name, email))
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(name = "User check")]
|
||||
pub async fn user_check(user_name: String) -> Bytes { unimplemented!() }
|
||||
|
Loading…
Reference in New Issue
Block a user