mirror of
				https://github.com/AppFlowy-IO/AppFlowy.git
				synced 2025-11-04 12:03:28 +00:00 
			
		
		
		
	[refactor]:
1. replace unbounded sender with directory call using static runtime 2. sync + send for handler
This commit is contained in:
		
							parent
							
								
									3328e29241
								
							
						
					
					
						commit
						7e1cf1222f
					
				@ -12,7 +12,7 @@ paste = "1"
 | 
				
			|||||||
futures-channel = "0.3.15"
 | 
					futures-channel = "0.3.15"
 | 
				
			||||||
futures = "0.3.15"
 | 
					futures = "0.3.15"
 | 
				
			||||||
futures-util = "0.3.15"
 | 
					futures-util = "0.3.15"
 | 
				
			||||||
bytes = "0.5"
 | 
					bytes = "1.0"
 | 
				
			||||||
tokio = { version = "1", features = ["full"] }
 | 
					tokio = { version = "1", features = ["full"] }
 | 
				
			||||||
uuid = { version = "0.8", features = ["serde", "v4"] }
 | 
					uuid = { version = "0.8", features = ["serde", "v4"] }
 | 
				
			||||||
log = "0.4.14"
 | 
					log = "0.4.14"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										174
									
								
								rust-lib/flowy-sys/src/dispatch.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								rust-lib/flowy-sys/src/dispatch.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,174 @@
 | 
				
			|||||||
 | 
					use crate::{
 | 
				
			||||||
 | 
					    error::{Error, InternalError, SystemError},
 | 
				
			||||||
 | 
					    module::{as_module_map, Event, Module, ModuleMap, ModuleRequest},
 | 
				
			||||||
 | 
					    request::Payload,
 | 
				
			||||||
 | 
					    response::EventResponse,
 | 
				
			||||||
 | 
					    service::{Service, ServiceFactory},
 | 
				
			||||||
 | 
					    util::tokio_default_runtime,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					use derivative::*;
 | 
				
			||||||
 | 
					use futures_core::future::BoxFuture;
 | 
				
			||||||
 | 
					use lazy_static::lazy_static;
 | 
				
			||||||
 | 
					use std::{
 | 
				
			||||||
 | 
					    fmt::{Debug, Display},
 | 
				
			||||||
 | 
					    hash::Hash,
 | 
				
			||||||
 | 
					    sync::RwLock,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lazy_static! {
 | 
				
			||||||
 | 
					    pub static ref EVENT_DISPATCH: RwLock<Option<EventDispatch>> = RwLock::new(None);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct EventDispatch {
 | 
				
			||||||
 | 
					    module_map: ModuleMap,
 | 
				
			||||||
 | 
					    runtime: tokio::runtime::Runtime,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl EventDispatch {
 | 
				
			||||||
 | 
					    pub fn construct<F>(module_factory: F)
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
 | 
					        F: FnOnce() -> Vec<Module>,
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        let modules = module_factory();
 | 
				
			||||||
 | 
					        let module_map = as_module_map(modules);
 | 
				
			||||||
 | 
					        let runtime = tokio_default_runtime().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let dispatch = EventDispatch {
 | 
				
			||||||
 | 
					            module_map,
 | 
				
			||||||
 | 
					            runtime,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        *(EVENT_DISPATCH.write().unwrap()) = Some(dispatch);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub async fn async_send<T>(request: DispatchRequest<T>) -> Result<EventResponse, SystemError>
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
 | 
					        T: 'static + Debug + Send + Sync,
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        match EVENT_DISPATCH.read() {
 | 
				
			||||||
 | 
					            Ok(dispatch) => {
 | 
				
			||||||
 | 
					                let dispatch = dispatch.as_ref().unwrap();
 | 
				
			||||||
 | 
					                let module_map = dispatch.module_map.clone();
 | 
				
			||||||
 | 
					                let service = Box::new(DispatchService { module_map });
 | 
				
			||||||
 | 
					                dispatch
 | 
				
			||||||
 | 
					                    .runtime
 | 
				
			||||||
 | 
					                    .spawn(async move { service.call(request).await })
 | 
				
			||||||
 | 
					                    .await
 | 
				
			||||||
 | 
					                    .unwrap_or_else(|e| {
 | 
				
			||||||
 | 
					                        let msg = format!("{:?}", e);
 | 
				
			||||||
 | 
					                        Ok(InternalError::new(msg).as_response())
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Err(e) => {
 | 
				
			||||||
 | 
					                let msg = format!("{:?}", e);
 | 
				
			||||||
 | 
					                Err(InternalError::new(msg).into())
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn sync_send<T>(request: DispatchRequest<T>) -> Result<EventResponse, SystemError>
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
 | 
					        T: 'static + Debug + Send + Sync,
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        futures::executor::block_on(async { EventDispatch::async_send(request).await })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub type BoxStreamCallback<T> = Box<dyn FnOnce(T, EventResponse) + 'static + Send + Sync>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Derivative)]
 | 
				
			||||||
 | 
					#[derivative(Debug)]
 | 
				
			||||||
 | 
					pub struct DispatchRequest<T>
 | 
				
			||||||
 | 
					where
 | 
				
			||||||
 | 
					    T: 'static + Debug,
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    pub config: T,
 | 
				
			||||||
 | 
					    pub event: Event,
 | 
				
			||||||
 | 
					    pub payload: Option<Payload>,
 | 
				
			||||||
 | 
					    #[derivative(Debug = "ignore")]
 | 
				
			||||||
 | 
					    pub callback: Option<BoxStreamCallback<T>>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<T> DispatchRequest<T>
 | 
				
			||||||
 | 
					where
 | 
				
			||||||
 | 
					    T: 'static + Debug,
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    pub fn new<E>(config: T, event: E) -> Self
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
 | 
					        E: Eq + Hash + Debug + Clone + Display,
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					            config,
 | 
				
			||||||
 | 
					            payload: None,
 | 
				
			||||||
 | 
					            event: event.into(),
 | 
				
			||||||
 | 
					            callback: None,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub(crate) struct DispatchService {
 | 
				
			||||||
 | 
					    pub(crate) module_map: ModuleMap,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<T> Service<DispatchRequest<T>> for DispatchService
 | 
				
			||||||
 | 
					where
 | 
				
			||||||
 | 
					    T: 'static + Debug + Send + Sync,
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    type Response = EventResponse;
 | 
				
			||||||
 | 
					    type Error = SystemError;
 | 
				
			||||||
 | 
					    type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn call(&self, dispatch_request: DispatchRequest<T>) -> Self::Future {
 | 
				
			||||||
 | 
					        let module_map = self.module_map.clone();
 | 
				
			||||||
 | 
					        let DispatchRequest {
 | 
				
			||||||
 | 
					            config,
 | 
				
			||||||
 | 
					            event,
 | 
				
			||||||
 | 
					            payload,
 | 
				
			||||||
 | 
					            callback,
 | 
				
			||||||
 | 
					        } = dispatch_request;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut request = ModuleRequest::new(event.clone());
 | 
				
			||||||
 | 
					        if let Some(payload) = payload {
 | 
				
			||||||
 | 
					            request = request.payload(payload);
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        Box::pin(async move {
 | 
				
			||||||
 | 
					            let result = {
 | 
				
			||||||
 | 
					                match module_map.get(&event) {
 | 
				
			||||||
 | 
					                    Some(module) => {
 | 
				
			||||||
 | 
					                        let fut = module.new_service(());
 | 
				
			||||||
 | 
					                        let service_fut = fut.await?.call(request);
 | 
				
			||||||
 | 
					                        service_fut.await
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    None => {
 | 
				
			||||||
 | 
					                        let msg = format!(
 | 
				
			||||||
 | 
					                            "Can not find the module to handle the request:{:?}",
 | 
				
			||||||
 | 
					                            request
 | 
				
			||||||
 | 
					                        );
 | 
				
			||||||
 | 
					                        Err(InternalError::new(msg).into())
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let response = result.unwrap_or_else(|e| e.into());
 | 
				
			||||||
 | 
					            if let Some(callback) = callback {
 | 
				
			||||||
 | 
					                callback(config, response.clone());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Ok(response)
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -7,7 +7,7 @@ use serde::{Serialize, Serializer};
 | 
				
			|||||||
use std::{fmt, option::NoneError};
 | 
					use std::{fmt, option::NoneError};
 | 
				
			||||||
use tokio::sync::mpsc::error::SendError;
 | 
					use tokio::sync::mpsc::error::SendError;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub trait Error: fmt::Debug + fmt::Display + DynClone {
 | 
					pub trait Error: fmt::Debug + fmt::Display + DynClone + Send + Sync {
 | 
				
			||||||
    fn status_code(&self) -> StatusCode;
 | 
					    fn status_code(&self) -> StatusCode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn as_response(&self) -> EventResponse { EventResponse::new(self.status_code()) }
 | 
					    fn as_response(&self) -> EventResponse { EventResponse::new(self.status_code()) }
 | 
				
			||||||
@ -83,21 +83,21 @@ impl<T: Clone> InternalError<T> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl<T> fmt::Debug for InternalError<T>
 | 
					impl<T> fmt::Debug for InternalError<T>
 | 
				
			||||||
where
 | 
					where
 | 
				
			||||||
    T: fmt::Debug + 'static + Clone,
 | 
					    T: fmt::Debug + 'static + Clone + Send + Sync,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.inner, f) }
 | 
					    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.inner, f) }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<T> fmt::Display for InternalError<T>
 | 
					impl<T> fmt::Display for InternalError<T>
 | 
				
			||||||
where
 | 
					where
 | 
				
			||||||
    T: fmt::Debug + fmt::Display + 'static + Clone,
 | 
					    T: fmt::Debug + fmt::Display + 'static + Clone + Send + Sync,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.inner, f) }
 | 
					    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.inner, f) }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<T> Error for InternalError<T>
 | 
					impl<T> Error for InternalError<T>
 | 
				
			||||||
where
 | 
					where
 | 
				
			||||||
    T: fmt::Debug + fmt::Display + 'static + Clone,
 | 
					    T: fmt::Debug + fmt::Display + 'static + Clone + Send + Sync,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    fn status_code(&self) -> StatusCode { StatusCode::Err }
 | 
					    fn status_code(&self) -> StatusCode { StatusCode::Err }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -8,9 +8,9 @@ mod rt;
 | 
				
			|||||||
mod service;
 | 
					mod service;
 | 
				
			||||||
mod util;
 | 
					mod util;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod sender;
 | 
					mod dispatch;
 | 
				
			||||||
mod system;
 | 
					mod system;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub mod prelude {
 | 
					pub mod prelude {
 | 
				
			||||||
    pub use crate::{error::*, module::*, request::*, response::*, rt::*, sender::*};
 | 
					    pub use crate::{dispatch::*, error::*, module::*, request::*, response::*, rt::*};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@ use std::{
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#[derive(Default)]
 | 
					#[derive(Default)]
 | 
				
			||||||
pub struct DataContainer {
 | 
					pub struct DataContainer {
 | 
				
			||||||
    map: HashMap<TypeId, Box<dyn Any>>,
 | 
					    map: HashMap<TypeId, Box<dyn Any + Sync + Send>>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl DataContainer {
 | 
					impl DataContainer {
 | 
				
			||||||
@ -16,27 +16,112 @@ impl DataContainer {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn insert<T: 'static>(&mut self, val: T) -> Option<T> {
 | 
					    pub fn insert<T>(&mut self, val: T) -> Option<T>
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
 | 
					        T: 'static + Send + Sync,
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
        self.map
 | 
					        self.map
 | 
				
			||||||
            .insert(TypeId::of::<T>(), Box::new(val))
 | 
					            .insert(TypeId::of::<T>(), Box::new(val))
 | 
				
			||||||
            .and_then(downcast_owned)
 | 
					            .and_then(downcast_owned)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn remove<T: 'static>(&mut self) -> Option<T> { self.map.remove(&TypeId::of::<T>()).and_then(downcast_owned) }
 | 
					    pub fn remove<T>(&mut self) -> Option<T>
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
    pub fn get<T: 'static>(&self) -> Option<&T> {
 | 
					        T: 'static + Send + Sync,
 | 
				
			||||||
        self.map.get(&TypeId::of::<T>()).and_then(|boxed| boxed.downcast_ref())
 | 
					    {
 | 
				
			||||||
 | 
					        self.map.remove(&TypeId::of::<T>()).and_then(downcast_owned)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
 | 
					    pub fn get<T>(&self) -> Option<&T>
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
 | 
					        T: 'static + Send + Sync,
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        self.map
 | 
				
			||||||
 | 
					            .get(&TypeId::of::<T>())
 | 
				
			||||||
 | 
					            .and_then(|boxed| boxed.downcast_ref())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn get_mut<T>(&mut self) -> Option<&mut T>
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
 | 
					        T: 'static + Send + Sync,
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
        self.map
 | 
					        self.map
 | 
				
			||||||
            .get_mut(&TypeId::of::<T>())
 | 
					            .get_mut(&TypeId::of::<T>())
 | 
				
			||||||
            .and_then(|boxed| boxed.downcast_mut())
 | 
					            .and_then(|boxed| boxed.downcast_mut())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn contains<T: 'static>(&self) -> bool { self.map.contains_key(&TypeId::of::<T>()) }
 | 
					    pub fn contains<T>(&self) -> bool
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
 | 
					        T: 'static + Send + Sync,
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        self.map.contains_key(&TypeId::of::<T>())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn extend(&mut self, other: DataContainer) { self.map.extend(other.map); }
 | 
					    pub fn extend(&mut self, other: DataContainer) { self.map.extend(other.map); }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn downcast_owned<T: 'static>(boxed: Box<dyn Any>) -> Option<T> { boxed.downcast().ok().map(|boxed| *boxed) }
 | 
					fn downcast_owned<T: 'static + Send + Sync>(boxed: Box<dyn Any + Send + Sync>) -> Option<T> {
 | 
				
			||||||
 | 
					    boxed.downcast().ok().map(|boxed| *boxed)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// use std::{
 | 
				
			||||||
 | 
					//     any::{Any, TypeId},
 | 
				
			||||||
 | 
					//     collections::HashMap,
 | 
				
			||||||
 | 
					//     sync::RwLock,
 | 
				
			||||||
 | 
					// };
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// #[derive(Default)]
 | 
				
			||||||
 | 
					// pub struct DataContainer {
 | 
				
			||||||
 | 
					//     map: RwLock<HashMap<TypeId, Box<dyn Any>>>,
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// impl DataContainer {
 | 
				
			||||||
 | 
					//     #[inline]
 | 
				
			||||||
 | 
					//     pub fn new() -> DataContainer {
 | 
				
			||||||
 | 
					//         DataContainer {
 | 
				
			||||||
 | 
					//             map: RwLock::new(HashMap::default()),
 | 
				
			||||||
 | 
					//         }
 | 
				
			||||||
 | 
					//     }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     pub fn insert<T: 'static>(&mut self, val: T) -> Option<T> {
 | 
				
			||||||
 | 
					//         self.map
 | 
				
			||||||
 | 
					//             .write()
 | 
				
			||||||
 | 
					//             .unwrap()
 | 
				
			||||||
 | 
					//             .insert(TypeId::of::<T>(), Box::new(val))
 | 
				
			||||||
 | 
					//             .and_then(downcast_owned)
 | 
				
			||||||
 | 
					//     }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     pub fn remove<T: 'static>(&mut self) -> Option<T> {
 | 
				
			||||||
 | 
					//         self.map
 | 
				
			||||||
 | 
					//             .write()
 | 
				
			||||||
 | 
					//             .unwrap()
 | 
				
			||||||
 | 
					//             .remove(&TypeId::of::<T>())
 | 
				
			||||||
 | 
					//             .and_then(downcast_owned)
 | 
				
			||||||
 | 
					//     }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     pub fn get<T: 'static>(&self) -> Option<&T> {
 | 
				
			||||||
 | 
					//         self.map
 | 
				
			||||||
 | 
					//             .read()
 | 
				
			||||||
 | 
					//             .unwrap()
 | 
				
			||||||
 | 
					//             .get(&TypeId::of::<T>())
 | 
				
			||||||
 | 
					//             .and_then(|boxed| boxed.downcast_ref())
 | 
				
			||||||
 | 
					//     }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
 | 
				
			||||||
 | 
					//         self.map
 | 
				
			||||||
 | 
					//             .write()
 | 
				
			||||||
 | 
					//             .unwrap()
 | 
				
			||||||
 | 
					//             .get_mut(&TypeId::of::<T>())
 | 
				
			||||||
 | 
					//             .and_then(|boxed| boxed.downcast_mut())
 | 
				
			||||||
 | 
					//     }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     pub fn contains<T: 'static>(&self) -> bool {
 | 
				
			||||||
 | 
					//         self.map.read().unwrap().contains_key(&TypeId::of::<T>())
 | 
				
			||||||
 | 
					//     }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     pub fn extend(&mut self, other: DataContainer) {
 | 
				
			||||||
 | 
					// self.map.write().unwrap().extend(other.map); } }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// fn downcast_owned<T: 'static>(boxed: Box<dyn Any>) -> Option<T> {
 | 
				
			||||||
 | 
					//     boxed.downcast().ok().map(|boxed| *boxed)
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
				
			|||||||
@ -5,29 +5,44 @@ use crate::{
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
use std::{ops::Deref, sync::Arc};
 | 
					use std::{ops::Deref, sync::Arc};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct ModuleData<T: ?Sized>(Arc<T>);
 | 
					pub struct ModuleData<T: ?Sized + Send + Sync>(Arc<T>);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<T> ModuleData<T> {
 | 
					impl<T> ModuleData<T>
 | 
				
			||||||
 | 
					where
 | 
				
			||||||
 | 
					    T: Send + Sync,
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
    pub fn new(data: T) -> Self { ModuleData(Arc::new(data)) }
 | 
					    pub fn new(data: T) -> Self { ModuleData(Arc::new(data)) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn get_ref(&self) -> &T { self.0.as_ref() }
 | 
					    pub fn get_ref(&self) -> &T { self.0.as_ref() }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<T: ?Sized> Deref for ModuleData<T> {
 | 
					impl<T> Deref for ModuleData<T>
 | 
				
			||||||
 | 
					where
 | 
				
			||||||
 | 
					    T: ?Sized + Send + Sync,
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
    type Target = Arc<T>;
 | 
					    type Target = Arc<T>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn deref(&self) -> &Arc<T> { &self.0 }
 | 
					    fn deref(&self) -> &Arc<T> { &self.0 }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<T: ?Sized> Clone for ModuleData<T> {
 | 
					impl<T> Clone for ModuleData<T>
 | 
				
			||||||
 | 
					where
 | 
				
			||||||
 | 
					    T: ?Sized + Send + Sync,
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
    fn clone(&self) -> ModuleData<T> { ModuleData(self.0.clone()) }
 | 
					    fn clone(&self) -> ModuleData<T> { ModuleData(self.0.clone()) }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<T: ?Sized> From<Arc<T>> for ModuleData<T> {
 | 
					impl<T> From<Arc<T>> for ModuleData<T>
 | 
				
			||||||
 | 
					where
 | 
				
			||||||
 | 
					    T: ?Sized + Send + Sync,
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
    fn from(arc: Arc<T>) -> Self { ModuleData(arc) }
 | 
					    fn from(arc: Arc<T>) -> Self { ModuleData(arc) }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<T: ?Sized + 'static> FromRequest for ModuleData<T> {
 | 
					impl<T> FromRequest for ModuleData<T>
 | 
				
			||||||
 | 
					where
 | 
				
			||||||
 | 
					    T: ?Sized + Send + Sync + 'static,
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
    type Error = SystemError;
 | 
					    type Error = SystemError;
 | 
				
			||||||
    type Future = Ready<Result<Self, SystemError>>;
 | 
					    type Future = Ready<Result<Self, SystemError>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -4,13 +4,11 @@ use std::{
 | 
				
			|||||||
    future::Future,
 | 
					    future::Future,
 | 
				
			||||||
    hash::Hash,
 | 
					    hash::Hash,
 | 
				
			||||||
    pin::Pin,
 | 
					    pin::Pin,
 | 
				
			||||||
    rc::Rc,
 | 
					 | 
				
			||||||
    task::{Context, Poll},
 | 
					    task::{Context, Poll},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use futures_core::{future::LocalBoxFuture, ready};
 | 
					use futures_core::ready;
 | 
				
			||||||
use pin_project::pin_project;
 | 
					use pin_project::pin_project;
 | 
				
			||||||
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    error::{InternalError, SystemError},
 | 
					    error::{InternalError, SystemError},
 | 
				
			||||||
@ -29,6 +27,21 @@ use crate::{
 | 
				
			|||||||
        ServiceResponse,
 | 
					        ServiceResponse,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					use futures_core::future::BoxFuture;
 | 
				
			||||||
 | 
					use std::sync::Arc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub type ModuleMap = Arc<HashMap<Event, Arc<Module>>>;
 | 
				
			||||||
 | 
					pub(crate) fn as_module_map(modules: Vec<Module>) -> ModuleMap {
 | 
				
			||||||
 | 
					    let mut module_map = HashMap::new();
 | 
				
			||||||
 | 
					    modules.into_iter().for_each(|m| {
 | 
				
			||||||
 | 
					        let events = m.events();
 | 
				
			||||||
 | 
					        let module = Arc::new(m);
 | 
				
			||||||
 | 
					        events.into_iter().for_each(|e| {
 | 
				
			||||||
 | 
					            module_map.insert(e, module.clone());
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    Arc::new(module_map)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
 | 
					#[derive(PartialEq, Eq, Hash, Debug, Clone)]
 | 
				
			||||||
pub struct Event(String);
 | 
					pub struct Event(String);
 | 
				
			||||||
@ -42,20 +55,15 @@ pub type EventServiceFactory = BoxServiceFactory<(), ServiceRequest, ServiceResp
 | 
				
			|||||||
pub struct Module {
 | 
					pub struct Module {
 | 
				
			||||||
    name: String,
 | 
					    name: String,
 | 
				
			||||||
    data: DataContainer,
 | 
					    data: DataContainer,
 | 
				
			||||||
    service_map: Rc<HashMap<Event, EventServiceFactory>>,
 | 
					    service_map: Arc<HashMap<Event, EventServiceFactory>>,
 | 
				
			||||||
    req_tx: UnboundedSender<ModuleRequest>,
 | 
					 | 
				
			||||||
    req_rx: UnboundedReceiver<ModuleRequest>,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Module {
 | 
					impl Module {
 | 
				
			||||||
    pub fn new() -> Self {
 | 
					    pub fn new() -> Self {
 | 
				
			||||||
        let (req_tx, req_rx) = unbounded_channel::<ModuleRequest>();
 | 
					 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            name: "".to_owned(),
 | 
					            name: "".to_owned(),
 | 
				
			||||||
            data: DataContainer::new(),
 | 
					            data: DataContainer::new(),
 | 
				
			||||||
            service_map: Rc::new(HashMap::new()),
 | 
					            service_map: Arc::new(HashMap::new()),
 | 
				
			||||||
            req_tx,
 | 
					 | 
				
			||||||
            req_rx,
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -64,7 +72,7 @@ impl Module {
 | 
				
			|||||||
        self
 | 
					        self
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn data<D: 'static>(mut self, data: D) -> Self {
 | 
					    pub fn data<D: 'static + Send + Sync>(mut self, data: D) -> Self {
 | 
				
			||||||
        self.data.insert(ModuleData::new(data));
 | 
					        self.data.insert(ModuleData::new(data));
 | 
				
			||||||
        self
 | 
					        self
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -72,8 +80,9 @@ impl Module {
 | 
				
			|||||||
    pub fn event<E, H, T, R>(mut self, event: E, handler: H) -> Self
 | 
					    pub fn event<E, H, T, R>(mut self, event: E, handler: H) -> Self
 | 
				
			||||||
    where
 | 
					    where
 | 
				
			||||||
        H: Handler<T, R>,
 | 
					        H: Handler<T, R>,
 | 
				
			||||||
        T: FromRequest + 'static,
 | 
					        T: FromRequest + 'static + Send + Sync,
 | 
				
			||||||
        R: Future + 'static,
 | 
					        <T as FromRequest>::Future: Sync + Send,
 | 
				
			||||||
 | 
					        R: Future + 'static + Send + Sync,
 | 
				
			||||||
        R::Output: Responder + 'static,
 | 
					        R::Output: Responder + 'static,
 | 
				
			||||||
        E: Eq + Hash + Debug + Clone + Display,
 | 
					        E: Eq + Hash + Debug + Clone + Display,
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -82,39 +91,17 @@ impl Module {
 | 
				
			|||||||
            log::error!("Duplicate Event: {:?}", &event);
 | 
					            log::error!("Duplicate Event: {:?}", &event);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Rc::get_mut(&mut self.service_map)
 | 
					        Arc::get_mut(&mut self.service_map)
 | 
				
			||||||
            .unwrap()
 | 
					            .unwrap()
 | 
				
			||||||
            .insert(event, factory(HandlerService::new(handler)));
 | 
					            .insert(event, factory(HandlerService::new(handler)));
 | 
				
			||||||
        self
 | 
					        self
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn forward_map(&self) -> HashMap<Event, UnboundedSender<ModuleRequest>> {
 | 
					    pub fn events(&self) -> Vec<Event> {
 | 
				
			||||||
        self.service_map
 | 
					        self.service_map
 | 
				
			||||||
            .keys()
 | 
					            .keys()
 | 
				
			||||||
            .map(|key| (key.clone(), self.req_tx.clone()))
 | 
					            .map(|key| key.clone())
 | 
				
			||||||
            .collect::<HashMap<_, _>>()
 | 
					            .collect::<Vec<_>>()
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub fn events(&self) -> Vec<Event> { self.service_map.keys().map(|key| key.clone()).collect::<Vec<_>>() }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Future for Module {
 | 
					 | 
				
			||||||
    type Output = ();
 | 
					 | 
				
			||||||
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
 | 
					 | 
				
			||||||
        loop {
 | 
					 | 
				
			||||||
            match ready!(Pin::new(&mut self.req_rx).poll_recv(cx)) {
 | 
					 | 
				
			||||||
                None => return Poll::Ready(()),
 | 
					 | 
				
			||||||
                Some(request) => {
 | 
					 | 
				
			||||||
                    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.id());
 | 
					 | 
				
			||||||
                        tokio::task::spawn_local(async move {
 | 
					 | 
				
			||||||
                            let _ = service.call(request).await;
 | 
					 | 
				
			||||||
                        });
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -140,23 +127,23 @@ impl ModuleRequest {
 | 
				
			|||||||
        self
 | 
					        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 id(&self) -> &str { &self.inner.id }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub(crate) fn event(&self) -> &Event { &self.inner.event }
 | 
					    pub(crate) fn event(&self) -> &Event { &self.inner.event }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl std::convert::Into<ServiceRequest> for ModuleRequest {
 | 
				
			||||||
 | 
					    fn into(self) -> ServiceRequest { ServiceRequest::new(self.inner, self.payload) }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl ServiceFactory<ModuleRequest> for Module {
 | 
					impl ServiceFactory<ModuleRequest> for Module {
 | 
				
			||||||
    type Response = EventResponse;
 | 
					    type Response = EventResponse;
 | 
				
			||||||
    type Error = SystemError;
 | 
					    type Error = SystemError;
 | 
				
			||||||
    type Service = BoxService<ModuleRequest, Self::Response, Self::Error>;
 | 
					    type Service = BoxService<ModuleRequest, Self::Response, Self::Error>;
 | 
				
			||||||
    type Context = ();
 | 
					    type Context = ();
 | 
				
			||||||
    type Future = LocalBoxFuture<'static, Result<Self::Service, Self::Error>>;
 | 
					    type Future = BoxFuture<'static, Result<Self::Service, Self::Error>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn new_service(&self, cfg: Self::Context) -> Self::Future {
 | 
					    fn new_service(&self, _cfg: Self::Context) -> Self::Future {
 | 
				
			||||||
        let service_map = self.service_map.clone();
 | 
					        let service_map = self.service_map.clone();
 | 
				
			||||||
        Box::pin(async move {
 | 
					        Box::pin(async move {
 | 
				
			||||||
            let service = ModuleService { service_map };
 | 
					            let service = ModuleService { service_map };
 | 
				
			||||||
@ -167,13 +154,13 @@ impl ServiceFactory<ModuleRequest> for Module {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct ModuleService {
 | 
					pub struct ModuleService {
 | 
				
			||||||
    service_map: Rc<HashMap<Event, EventServiceFactory>>,
 | 
					    service_map: Arc<HashMap<Event, EventServiceFactory>>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Service<ModuleRequest> for ModuleService {
 | 
					impl Service<ModuleRequest> for ModuleService {
 | 
				
			||||||
    type Response = EventResponse;
 | 
					    type Response = EventResponse;
 | 
				
			||||||
    type Error = SystemError;
 | 
					    type Error = SystemError;
 | 
				
			||||||
    type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
 | 
					    type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn call(&self, request: ModuleRequest) -> Self::Future {
 | 
					    fn call(&self, request: ModuleRequest) -> Self::Future {
 | 
				
			||||||
        log::trace!("Call module service for request {}", &request.id());
 | 
					        log::trace!("Call module service for request {}", &request.id());
 | 
				
			||||||
@ -183,8 +170,7 @@ impl Service<ModuleRequest> for ModuleService {
 | 
				
			|||||||
                let fut = ModuleServiceFuture {
 | 
					                let fut = ModuleServiceFuture {
 | 
				
			||||||
                    fut: Box::pin(async {
 | 
					                    fut: Box::pin(async {
 | 
				
			||||||
                        let service = service_fut.await?;
 | 
					                        let service = service_fut.await?;
 | 
				
			||||||
                        let request = request.into_service_request();
 | 
					                        service.call(request.into()).await
 | 
				
			||||||
                        service.call(request).await
 | 
					 | 
				
			||||||
                    }),
 | 
					                    }),
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
                Box::pin(async move { Ok(fut.await.unwrap_or_else(|e| e.into())) })
 | 
					                Box::pin(async move { Ok(fut.await.unwrap_or_else(|e| e.into())) })
 | 
				
			||||||
@ -200,7 +186,7 @@ impl Service<ModuleRequest> for ModuleService {
 | 
				
			|||||||
#[pin_project]
 | 
					#[pin_project]
 | 
				
			||||||
pub struct ModuleServiceFuture {
 | 
					pub struct ModuleServiceFuture {
 | 
				
			||||||
    #[pin]
 | 
					    #[pin]
 | 
				
			||||||
    fut: LocalBoxFuture<'static, Result<ServiceResponse, SystemError>>,
 | 
					    fut: BoxFuture<'static, Result<ServiceResponse, SystemError>>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Future for ModuleServiceFuture {
 | 
					impl Future for ModuleServiceFuture {
 | 
				
			||||||
 | 
				
			|||||||
@ -4,15 +4,13 @@ use crate::{
 | 
				
			|||||||
    error::{InternalError, SystemError},
 | 
					    error::{InternalError, SystemError},
 | 
				
			||||||
    module::Event,
 | 
					    module::Event,
 | 
				
			||||||
    request::payload::Payload,
 | 
					    request::payload::Payload,
 | 
				
			||||||
    response::Responder,
 | 
					 | 
				
			||||||
    util::ready::{ready, Ready},
 | 
					    util::ready::{ready, Ready},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::response::{EventResponse, ResponseBuilder};
 | 
					
 | 
				
			||||||
use futures_core::ready;
 | 
					use futures_core::ready;
 | 
				
			||||||
use std::{
 | 
					use std::{
 | 
				
			||||||
    fmt::Debug,
 | 
					    fmt::Debug,
 | 
				
			||||||
    hash::Hash,
 | 
					 | 
				
			||||||
    ops,
 | 
					    ops,
 | 
				
			||||||
    pin::Pin,
 | 
					    pin::Pin,
 | 
				
			||||||
    task::{Context, Poll},
 | 
					    task::{Context, Poll},
 | 
				
			||||||
@ -135,8 +133,11 @@ where
 | 
				
			|||||||
        match payload {
 | 
					        match payload {
 | 
				
			||||||
            Payload::None => ready(Err(unexpected_none_payload(req))),
 | 
					            Payload::None => ready(Err(unexpected_none_payload(req))),
 | 
				
			||||||
            Payload::Bytes(bytes) => {
 | 
					            Payload::Bytes(bytes) => {
 | 
				
			||||||
                let data: T = bincode::deserialize(bytes).unwrap();
 | 
					                let s = String::from_utf8_lossy(bytes);
 | 
				
			||||||
                ready(Ok(Data(data)))
 | 
					                match serde_json::from_str(s.as_ref()) {
 | 
				
			||||||
 | 
					                    Ok(data) => ready(Ok(Data(data))),
 | 
				
			||||||
 | 
					                    Err(e) => ready(Err(InternalError::new(format!("{:?}", e)).into())),
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
use bytes::{Buf, Bytes};
 | 
					use bytes::{Bytes};
 | 
				
			||||||
use serde::{Deserialize, Serialize};
 | 
					
 | 
				
			||||||
use std::{fmt, fmt::Formatter};
 | 
					use std::{fmt, fmt::Formatter};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone)]
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
@ -27,7 +27,10 @@ impl std::convert::Into<ResponseData> for &'_ String {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl std::convert::Into<ResponseData> for Bytes {
 | 
					impl std::convert::Into<ResponseData> for Bytes {
 | 
				
			||||||
    fn into(self) -> ResponseData { ResponseData::Bytes(self.bytes().to_vec()) }
 | 
					    fn into(self) -> ResponseData {
 | 
				
			||||||
 | 
					        // Opti(nathan): do not copy the bytes?
 | 
				
			||||||
 | 
					        ResponseData::Bytes(self.as_ref().to_vec())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl std::convert::Into<ResponseData> for Vec<u8> {
 | 
					impl std::convert::Into<ResponseData> for Vec<u8> {
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@ use crate::{
 | 
				
			|||||||
    response::{EventResponse, ResponseBuilder},
 | 
					    response::{EventResponse, ResponseBuilder},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use bytes::Bytes;
 | 
					use bytes::Bytes;
 | 
				
			||||||
use std::ops;
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub trait Responder {
 | 
					pub trait Responder {
 | 
				
			||||||
    fn respond_to(self, req: &EventRequest) -> EventResponse;
 | 
					    fn respond_to(self, req: &EventRequest) -> EventResponse;
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@ use crate::{
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::request::Data;
 | 
					use crate::request::Data;
 | 
				
			||||||
use serde::{Deserialize, Serialize, Serializer};
 | 
					
 | 
				
			||||||
use std::{fmt, fmt::Formatter};
 | 
					use std::{fmt, fmt::Formatter};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Clone, Debug, Eq, PartialEq)]
 | 
					#[derive(Clone, Debug, Eq, PartialEq)]
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
use std::{future::Future, io, thread};
 | 
					use crate::util::tokio_default_runtime;
 | 
				
			||||||
use thread_id;
 | 
					use std::{future::Future, io};
 | 
				
			||||||
use tokio::{runtime, task::LocalSet};
 | 
					use tokio::{runtime, task::LocalSet};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
@ -10,26 +10,7 @@ pub struct Runtime {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl Runtime {
 | 
					impl Runtime {
 | 
				
			||||||
    pub fn new() -> io::Result<Runtime> {
 | 
					    pub fn new() -> io::Result<Runtime> {
 | 
				
			||||||
        let rt = runtime::Builder::new_multi_thread()
 | 
					        let rt = tokio_default_runtime()?;
 | 
				
			||||||
            .thread_name("flowy-sys")
 | 
					 | 
				
			||||||
            .enable_io()
 | 
					 | 
				
			||||||
            .enable_time()
 | 
					 | 
				
			||||||
            .on_thread_start(move || {
 | 
					 | 
				
			||||||
                log::trace!(
 | 
					 | 
				
			||||||
                    "{:?} thread started: thread_id= {}",
 | 
					 | 
				
			||||||
                    thread::current(),
 | 
					 | 
				
			||||||
                    thread_id::get()
 | 
					 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .on_thread_stop(move || {
 | 
					 | 
				
			||||||
                log::trace!(
 | 
					 | 
				
			||||||
                    "{:?} thread stopping: thread_id= {}",
 | 
					 | 
				
			||||||
                    thread::current(),
 | 
					 | 
				
			||||||
                    thread_id::get(),
 | 
					 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .build()?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Ok(Runtime {
 | 
					        Ok(Runtime {
 | 
				
			||||||
            rt,
 | 
					            rt,
 | 
				
			||||||
            local: LocalSet::new(),
 | 
					            local: LocalSet::new(),
 | 
				
			||||||
 | 
				
			|||||||
@ -1,99 +0,0 @@
 | 
				
			|||||||
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!() }
 | 
					 | 
				
			||||||
// }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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<T> SenderRequest<T>
 | 
					 | 
				
			||||||
where
 | 
					 | 
				
			||||||
    T: 'static + Debug,
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    pub fn new<E>(config: T, event: E) -> Self
 | 
					 | 
				
			||||||
    where
 | 
					 | 
				
			||||||
        E: Eq + Hash + Debug + Clone + Display,
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        Self {
 | 
					 | 
				
			||||||
            config,
 | 
					 | 
				
			||||||
            payload: None,
 | 
					 | 
				
			||||||
            event: event.into(),
 | 
					 | 
				
			||||||
            callback: None,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    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,5 +0,0 @@
 | 
				
			|||||||
mod data;
 | 
					 | 
				
			||||||
mod sender;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub use data::*;
 | 
					 | 
				
			||||||
pub use sender::*;
 | 
					 | 
				
			||||||
@ -1,167 +0,0 @@
 | 
				
			|||||||
use crate::{
 | 
					 | 
				
			||||||
    error::{InternalError, SystemError},
 | 
					 | 
				
			||||||
    module::ModuleRequest,
 | 
					 | 
				
			||||||
    request::{EventRequest, Payload},
 | 
					 | 
				
			||||||
    response::EventResponse,
 | 
					 | 
				
			||||||
    sender::SenderRequest,
 | 
					 | 
				
			||||||
    service::{BoxService, Service, ServiceFactory},
 | 
					 | 
				
			||||||
    system::ModuleMap,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
use futures_core::{future::LocalBoxFuture, ready, task::Context};
 | 
					 | 
				
			||||||
use std::{fmt::Debug, future::Future};
 | 
					 | 
				
			||||||
use tokio::{
 | 
					 | 
				
			||||||
    macros::support::{Pin, Poll},
 | 
					 | 
				
			||||||
    sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
macro_rules! service_factor_impl {
 | 
					 | 
				
			||||||
    ($name:ident) => {
 | 
					 | 
				
			||||||
        #[allow(non_snake_case, missing_docs)]
 | 
					 | 
				
			||||||
        impl<T> ServiceFactory<SenderRequest<T>> for $name<T>
 | 
					 | 
				
			||||||
        where
 | 
					 | 
				
			||||||
            T: 'static + Debug,
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            type Response = EventResponse;
 | 
					 | 
				
			||||||
            type Error = SystemError;
 | 
					 | 
				
			||||||
            type Service = BoxService<SenderRequest<T>, Self::Response, Self::Error>;
 | 
					 | 
				
			||||||
            type Context = ();
 | 
					 | 
				
			||||||
            type Future = LocalBoxFuture<'static, Result<Self::Service, Self::Error>>;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            fn new_service(&self, _cfg: Self::Context) -> Self::Future {
 | 
					 | 
				
			||||||
                let module_map = self.module_map.clone();
 | 
					 | 
				
			||||||
                let service = Box::new(SenderService { module_map });
 | 
					 | 
				
			||||||
                Box::pin(async move { Ok(service as Self::Service) })
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct SenderService {
 | 
					 | 
				
			||||||
    module_map: ModuleMap,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<T> Service<SenderRequest<T>> for SenderService
 | 
					 | 
				
			||||||
where
 | 
					 | 
				
			||||||
    T: 'static + Debug,
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    type Response = EventResponse;
 | 
					 | 
				
			||||||
    type Error = SystemError;
 | 
					 | 
				
			||||||
    type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn call(&self, data: SenderRequest<T>) -> Self::Future {
 | 
					 | 
				
			||||||
        let module_map = self.module_map.clone();
 | 
					 | 
				
			||||||
        let SenderRequest {
 | 
					 | 
				
			||||||
            config,
 | 
					 | 
				
			||||||
            event,
 | 
					 | 
				
			||||||
            payload,
 | 
					 | 
				
			||||||
            callback,
 | 
					 | 
				
			||||||
        } = data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let mut request = ModuleRequest::new(event.clone());
 | 
					 | 
				
			||||||
        if let Some(payload) = payload {
 | 
					 | 
				
			||||||
            request = request.payload(payload);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let fut = async move {
 | 
					 | 
				
			||||||
            let result = {
 | 
					 | 
				
			||||||
                match module_map.get(&event) {
 | 
					 | 
				
			||||||
                    Some(module) => {
 | 
					 | 
				
			||||||
                        let fut = module.new_service(());
 | 
					 | 
				
			||||||
                        let service_fut = fut.await?.call(request);
 | 
					 | 
				
			||||||
                        service_fut.await
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                    None => {
 | 
					 | 
				
			||||||
                        let msg = format!("Can not find the module to handle the request:{:?}", request);
 | 
					 | 
				
			||||||
                        Err(InternalError::new(msg).into())
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            let response = result.unwrap_or_else(|e| e.into());
 | 
					 | 
				
			||||||
            if let Some(callback) = callback {
 | 
					 | 
				
			||||||
                callback(config, response.clone());
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            Ok(response)
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        Box::pin(fut)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub struct Sender<T>
 | 
					 | 
				
			||||||
where
 | 
					 | 
				
			||||||
    T: 'static + Debug,
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    module_map: ModuleMap,
 | 
					 | 
				
			||||||
    data_tx: UnboundedSender<SenderRequest<T>>,
 | 
					 | 
				
			||||||
    data_rx: Option<UnboundedReceiver<SenderRequest<T>>>,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
service_factor_impl!(Sender);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<T> Sender<T>
 | 
					 | 
				
			||||||
where
 | 
					 | 
				
			||||||
    T: 'static + Debug,
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    pub fn new(module_map: ModuleMap) -> Self {
 | 
					 | 
				
			||||||
        let (data_tx, data_rx) = unbounded_channel::<SenderRequest<T>>();
 | 
					 | 
				
			||||||
        Self {
 | 
					 | 
				
			||||||
            module_map,
 | 
					 | 
				
			||||||
            data_tx,
 | 
					 | 
				
			||||||
            data_rx: Some(data_rx),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub fn async_send(&self, data: SenderRequest<T>) { let _ = self.data_tx.send(data); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub fn sync_send(&self, data: SenderRequest<T>) -> EventResponse {
 | 
					 | 
				
			||||||
        let factory = self.new_service(());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        futures::executor::block_on(async {
 | 
					 | 
				
			||||||
            let service = factory.await.unwrap();
 | 
					 | 
				
			||||||
            service.call(data).await.unwrap()
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub fn take_rx(&mut self) -> UnboundedReceiver<SenderRequest<T>> { self.data_rx.take().unwrap() }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub struct SenderRunner<T>
 | 
					 | 
				
			||||||
where
 | 
					 | 
				
			||||||
    T: 'static + Debug,
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    module_map: ModuleMap,
 | 
					 | 
				
			||||||
    data_rx: UnboundedReceiver<SenderRequest<T>>,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
service_factor_impl!(SenderRunner);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<T> SenderRunner<T>
 | 
					 | 
				
			||||||
where
 | 
					 | 
				
			||||||
    T: 'static + Debug,
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    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 + Debug,
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    type Output = ();
 | 
					 | 
				
			||||||
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
 | 
					 | 
				
			||||||
        loop {
 | 
					 | 
				
			||||||
            match ready!(Pin::new(&mut self.data_rx).poll_recv(cx)) {
 | 
					 | 
				
			||||||
                None => return Poll::Ready(()),
 | 
					 | 
				
			||||||
                Some(ctx) => {
 | 
					 | 
				
			||||||
                    let factory = self.new_service(());
 | 
					 | 
				
			||||||
                    tokio::task::spawn_local(async move {
 | 
					 | 
				
			||||||
                        let service = factory.await.unwrap();
 | 
					 | 
				
			||||||
                        let _ = service.call(ctx).await;
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,27 +1,31 @@
 | 
				
			|||||||
use crate::service::{Service, ServiceFactory};
 | 
					use crate::service::{Service, ServiceFactory};
 | 
				
			||||||
use futures_core::future::LocalBoxFuture;
 | 
					use futures_core::future::{BoxFuture};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn factory<SF, Req>(factory: SF) -> BoxServiceFactory<SF::Context, Req, SF::Response, SF::Error>
 | 
					pub fn factory<SF, Req>(factory: SF) -> BoxServiceFactory<SF::Context, Req, SF::Response, SF::Error>
 | 
				
			||||||
where
 | 
					where
 | 
				
			||||||
    SF: ServiceFactory<Req> + 'static,
 | 
					    SF: ServiceFactory<Req> + 'static + Sync + Send,
 | 
				
			||||||
    Req: 'static,
 | 
					    Req: 'static,
 | 
				
			||||||
    SF::Response: 'static,
 | 
					    SF::Response: 'static,
 | 
				
			||||||
    SF::Service: 'static,
 | 
					    SF::Service: 'static,
 | 
				
			||||||
    SF::Future: 'static,
 | 
					    SF::Future: 'static,
 | 
				
			||||||
    SF::Error: 'static,
 | 
					    SF::Error: 'static + Send + Sync,
 | 
				
			||||||
 | 
					    <SF as ServiceFactory<Req>>::Service: Sync + Send,
 | 
				
			||||||
 | 
					    <<SF as ServiceFactory<Req>>::Service as Service<Req>>::Future: Send + Sync,
 | 
				
			||||||
 | 
					    <SF as ServiceFactory<Req>>::Future: Send + Sync,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    BoxServiceFactory(Box::new(FactoryWrapper(factory)))
 | 
					    BoxServiceFactory(Box::new(FactoryWrapper(factory)))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Inner<Cfg, Req, Res, Err> = Box<
 | 
					type Inner<Cfg, Req, Res, Err> = Box<
 | 
				
			||||||
    dyn ServiceFactory<
 | 
					    dyn ServiceFactory<
 | 
				
			||||||
        Req,
 | 
					            Req,
 | 
				
			||||||
        Context = Cfg,
 | 
					            Context = Cfg,
 | 
				
			||||||
        Response = Res,
 | 
					            Response = Res,
 | 
				
			||||||
        Error = Err,
 | 
					            Error = Err,
 | 
				
			||||||
        Service = BoxService<Req, Res, Err>,
 | 
					            Service = BoxService<Req, Res, Err>,
 | 
				
			||||||
        Future = LocalBoxFuture<'static, Result<BoxService<Req, Res, Err>, Err>>,
 | 
					            Future = BoxFuture<'static, Result<BoxService<Req, Res, Err>, Err>>,
 | 
				
			||||||
    >,
 | 
					        > + Sync
 | 
				
			||||||
 | 
					        + Send,
 | 
				
			||||||
>;
 | 
					>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct BoxServiceFactory<Cfg, Req, Res, Err>(Inner<Cfg, Req, Res, Err>);
 | 
					pub struct BoxServiceFactory<Cfg, Req, Res, Err>(Inner<Cfg, Req, Res, Err>);
 | 
				
			||||||
@ -35,23 +39,26 @@ where
 | 
				
			|||||||
    type Error = Err;
 | 
					    type Error = Err;
 | 
				
			||||||
    type Service = BoxService<Req, Res, Err>;
 | 
					    type Service = BoxService<Req, Res, Err>;
 | 
				
			||||||
    type Context = Cfg;
 | 
					    type Context = Cfg;
 | 
				
			||||||
    type Future = LocalBoxFuture<'static, Result<Self::Service, Self::Error>>;
 | 
					    type Future = BoxFuture<'static, Result<Self::Service, Self::Error>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn new_service(&self, cfg: Cfg) -> Self::Future { self.0.new_service(cfg) }
 | 
					    fn new_service(&self, cfg: Cfg) -> Self::Future { self.0.new_service(cfg) }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub type BoxService<Req, Res, Err> =
 | 
					pub type BoxService<Req, Res, Err> = Box<
 | 
				
			||||||
    Box<dyn Service<Req, Response = Res, Error = Err, Future = LocalBoxFuture<'static, Result<Res, Err>>>>;
 | 
					    dyn Service<Req, Response = Res, Error = Err, Future = BoxFuture<'static, Result<Res, Err>>>
 | 
				
			||||||
 | 
					        + Sync
 | 
				
			||||||
 | 
					        + Send,
 | 
				
			||||||
 | 
					>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[allow(dead_code)]
 | 
					// #[allow(dead_code)]
 | 
				
			||||||
pub fn service<S, Req>(service: S) -> BoxService<Req, S::Response, S::Error>
 | 
					// pub fn service<S, Req>(service: S) -> BoxService<Req, S::Response, S::Error>
 | 
				
			||||||
where
 | 
					// where
 | 
				
			||||||
    S: Service<Req> + 'static,
 | 
					//     S: Service<Req> + 'static,
 | 
				
			||||||
    Req: 'static,
 | 
					//     Req: 'static,
 | 
				
			||||||
    S::Future: 'static,
 | 
					//     S::Future: 'static,
 | 
				
			||||||
{
 | 
					// {
 | 
				
			||||||
    Box::new(ServiceWrapper::new(service))
 | 
					//     Box::new(ServiceWrapper::new(service))
 | 
				
			||||||
}
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<S, Req> Service<Req> for Box<S>
 | 
					impl<S, Req> Service<Req> for Box<S>
 | 
				
			||||||
where
 | 
					where
 | 
				
			||||||
@ -75,11 +82,11 @@ impl<S> ServiceWrapper<S> {
 | 
				
			|||||||
impl<S, Req, Res, Err> Service<Req> for ServiceWrapper<S>
 | 
					impl<S, Req, Res, Err> Service<Req> for ServiceWrapper<S>
 | 
				
			||||||
where
 | 
					where
 | 
				
			||||||
    S: Service<Req, Response = Res, Error = Err>,
 | 
					    S: Service<Req, Response = Res, Error = Err>,
 | 
				
			||||||
    S::Future: 'static,
 | 
					    S::Future: 'static + Send + Sync,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    type Response = Res;
 | 
					    type Response = Res;
 | 
				
			||||||
    type Error = Err;
 | 
					    type Error = Err;
 | 
				
			||||||
    type Future = LocalBoxFuture<'static, Result<Res, Err>>;
 | 
					    type Future = BoxFuture<'static, Result<Res, Err>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn call(&self, req: Req) -> Self::Future { Box::pin(self.inner.call(req)) }
 | 
					    fn call(&self, req: Req) -> Self::Future { Box::pin(self.inner.call(req)) }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -93,17 +100,21 @@ where
 | 
				
			|||||||
    Err: 'static,
 | 
					    Err: 'static,
 | 
				
			||||||
    SF: ServiceFactory<Req, Context = Cfg, Response = Res, Error = Err>,
 | 
					    SF: ServiceFactory<Req, Context = Cfg, Response = Res, Error = Err>,
 | 
				
			||||||
    SF::Future: 'static,
 | 
					    SF::Future: 'static,
 | 
				
			||||||
    SF::Service: 'static,
 | 
					    SF::Service: 'static + Send + Sync,
 | 
				
			||||||
    <SF::Service as Service<Req>>::Future: 'static,
 | 
					    <<SF as ServiceFactory<Req>>::Service as Service<Req>>::Future: Send + Sync + 'static,
 | 
				
			||||||
 | 
					    <SF as ServiceFactory<Req>>::Future: Send + Sync,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    type Response = Res;
 | 
					    type Response = Res;
 | 
				
			||||||
    type Error = Err;
 | 
					    type Error = Err;
 | 
				
			||||||
    type Service = BoxService<Req, Res, Err>;
 | 
					    type Service = BoxService<Req, Res, Err>;
 | 
				
			||||||
    type Context = Cfg;
 | 
					    type Context = Cfg;
 | 
				
			||||||
    type Future = LocalBoxFuture<'static, Result<Self::Service, Self::Error>>;
 | 
					    type Future = BoxFuture<'static, Result<Self::Service, Self::Error>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn new_service(&self, cfg: Cfg) -> Self::Future {
 | 
					    fn new_service(&self, cfg: Cfg) -> Self::Future {
 | 
				
			||||||
        let f = self.0.new_service(cfg);
 | 
					        let f = self.0.new_service(cfg);
 | 
				
			||||||
        Box::pin(async { f.await.map(|s| Box::new(ServiceWrapper::new(s)) as Self::Service) })
 | 
					        Box::pin(async {
 | 
				
			||||||
 | 
					            f.await
 | 
				
			||||||
 | 
					                .map(|s| Box::new(ServiceWrapper::new(s)) as Self::Service)
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -16,9 +16,9 @@ use crate::{
 | 
				
			|||||||
    util::ready::*,
 | 
					    util::ready::*,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub trait Handler<T, R>: Clone + 'static
 | 
					pub trait Handler<T, R>: Clone + 'static + Sync + Send
 | 
				
			||||||
where
 | 
					where
 | 
				
			||||||
    R: Future,
 | 
					    R: Future + Send + Sync,
 | 
				
			||||||
    R::Output: Responder,
 | 
					    R::Output: Responder,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    fn call(&self, param: T) -> R;
 | 
					    fn call(&self, param: T) -> R;
 | 
				
			||||||
@ -28,7 +28,7 @@ pub struct HandlerService<H, T, R>
 | 
				
			|||||||
where
 | 
					where
 | 
				
			||||||
    H: Handler<T, R>,
 | 
					    H: Handler<T, R>,
 | 
				
			||||||
    T: FromRequest,
 | 
					    T: FromRequest,
 | 
				
			||||||
    R: Future,
 | 
					    R: Future + Sync + Send,
 | 
				
			||||||
    R::Output: Responder,
 | 
					    R::Output: Responder,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    handler: H,
 | 
					    handler: H,
 | 
				
			||||||
@ -39,7 +39,7 @@ impl<H, T, R> HandlerService<H, T, R>
 | 
				
			|||||||
where
 | 
					where
 | 
				
			||||||
    H: Handler<T, R>,
 | 
					    H: Handler<T, R>,
 | 
				
			||||||
    T: FromRequest,
 | 
					    T: FromRequest,
 | 
				
			||||||
    R: Future,
 | 
					    R: Future + Sync + Send,
 | 
				
			||||||
    R::Output: Responder,
 | 
					    R::Output: Responder,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    pub fn new(handler: H) -> Self {
 | 
					    pub fn new(handler: H) -> Self {
 | 
				
			||||||
@ -54,7 +54,7 @@ impl<H, T, R> Clone for HandlerService<H, T, R>
 | 
				
			|||||||
where
 | 
					where
 | 
				
			||||||
    H: Handler<T, R>,
 | 
					    H: Handler<T, R>,
 | 
				
			||||||
    T: FromRequest,
 | 
					    T: FromRequest,
 | 
				
			||||||
    R: Future,
 | 
					    R: Future + Sync + Send,
 | 
				
			||||||
    R::Output: Responder,
 | 
					    R::Output: Responder,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    fn clone(&self) -> Self {
 | 
					    fn clone(&self) -> Self {
 | 
				
			||||||
@ -69,7 +69,7 @@ impl<F, T, R> ServiceFactory<ServiceRequest> for HandlerService<F, T, R>
 | 
				
			|||||||
where
 | 
					where
 | 
				
			||||||
    F: Handler<T, R>,
 | 
					    F: Handler<T, R>,
 | 
				
			||||||
    T: FromRequest,
 | 
					    T: FromRequest,
 | 
				
			||||||
    R: Future,
 | 
					    R: Future + Send + Sync,
 | 
				
			||||||
    R::Output: Responder,
 | 
					    R::Output: Responder,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    type Response = ServiceResponse;
 | 
					    type Response = ServiceResponse;
 | 
				
			||||||
@ -85,7 +85,7 @@ impl<H, T, R> Service<ServiceRequest> for HandlerService<H, T, R>
 | 
				
			|||||||
where
 | 
					where
 | 
				
			||||||
    H: Handler<T, R>,
 | 
					    H: Handler<T, R>,
 | 
				
			||||||
    T: FromRequest,
 | 
					    T: FromRequest,
 | 
				
			||||||
    R: Future,
 | 
					    R: Future + Sync + Send,
 | 
				
			||||||
    R::Output: Responder,
 | 
					    R::Output: Responder,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    type Response = ServiceResponse;
 | 
					    type Response = ServiceResponse;
 | 
				
			||||||
@ -104,7 +104,7 @@ pub enum HandlerServiceFuture<H, T, R>
 | 
				
			|||||||
where
 | 
					where
 | 
				
			||||||
    H: Handler<T, R>,
 | 
					    H: Handler<T, R>,
 | 
				
			||||||
    T: FromRequest,
 | 
					    T: FromRequest,
 | 
				
			||||||
    R: Future,
 | 
					    R: Future + Sync + Send,
 | 
				
			||||||
    R::Output: Responder,
 | 
					    R::Output: Responder,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Extract(#[pin] T::Future, Option<EventRequest>, H),
 | 
					    Extract(#[pin] T::Future, Option<EventRequest>, H),
 | 
				
			||||||
@ -115,7 +115,7 @@ impl<F, T, R> Future for HandlerServiceFuture<F, T, R>
 | 
				
			|||||||
where
 | 
					where
 | 
				
			||||||
    F: Handler<T, R>,
 | 
					    F: Handler<T, R>,
 | 
				
			||||||
    T: FromRequest,
 | 
					    T: FromRequest,
 | 
				
			||||||
    R: Future,
 | 
					    R: Future + Sync + Send,
 | 
				
			||||||
    R::Output: Responder,
 | 
					    R::Output: Responder,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    type Output = Result<ServiceResponse, SystemError>;
 | 
					    type Output = Result<ServiceResponse, SystemError>;
 | 
				
			||||||
@ -151,8 +151,8 @@ where
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
macro_rules! factory_tuple ({ $($param:ident)* } => {
 | 
					macro_rules! factory_tuple ({ $($param:ident)* } => {
 | 
				
			||||||
    impl<Func, $($param,)* Res> Handler<($($param,)*), Res> for Func
 | 
					    impl<Func, $($param,)* Res> Handler<($($param,)*), Res> for Func
 | 
				
			||||||
    where Func: Fn($($param),*) -> Res + Clone + 'static,
 | 
					    where Func: Fn($($param),*) -> Res + Clone + 'static + Sync + Send,
 | 
				
			||||||
          Res: Future,
 | 
					          Res: Future + Sync + Send,
 | 
				
			||||||
          Res::Output: Responder,
 | 
					          Res::Output: Responder,
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        #[allow(non_snake_case)]
 | 
					        #[allow(non_snake_case)]
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,9 @@
 | 
				
			|||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    module::{Event, Module},
 | 
					    module::{as_module_map, Module, ModuleMap},
 | 
				
			||||||
    rt::Runtime,
 | 
					    rt::Runtime,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use futures_core::{ready, task::Context};
 | 
					use futures_core::{ready, task::Context};
 | 
				
			||||||
use std::{cell::RefCell, collections::HashMap, fmt::Debug, future::Future, io, rc::Rc, sync::Arc};
 | 
					use std::{cell::RefCell, fmt::Debug, future::Future, io, sync::Arc};
 | 
				
			||||||
use tokio::{
 | 
					use tokio::{
 | 
				
			||||||
    macros::support::{Pin, Poll},
 | 
					    macros::support::{Pin, Poll},
 | 
				
			||||||
    sync::{
 | 
					    sync::{
 | 
				
			||||||
@ -21,7 +21,6 @@ pub enum SystemCommand {
 | 
				
			|||||||
    Exit(i8),
 | 
					    Exit(i8),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub type ModuleMap = Rc<HashMap<Event, Rc<Module>>>;
 | 
					 | 
				
			||||||
pub struct FlowySystem {
 | 
					pub struct FlowySystem {
 | 
				
			||||||
    sys_cmd_tx: UnboundedSender<SystemCommand>,
 | 
					    sys_cmd_tx: UnboundedSender<SystemCommand>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -32,7 +31,7 @@ impl FlowySystem {
 | 
				
			|||||||
        F: FnOnce() -> Vec<Module>,
 | 
					        F: FnOnce() -> Vec<Module>,
 | 
				
			||||||
        S: FnOnce(ModuleMap, &Runtime),
 | 
					        S: FnOnce(ModuleMap, &Runtime),
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        let runtime = Runtime::new().unwrap();
 | 
					        let runtime = Arc::new(Runtime::new().unwrap());
 | 
				
			||||||
        let (sys_cmd_tx, sys_cmd_rx) = unbounded_channel::<SystemCommand>();
 | 
					        let (sys_cmd_tx, sys_cmd_rx) = unbounded_channel::<SystemCommand>();
 | 
				
			||||||
        let (stop_tx, stop_rx) = oneshot::channel();
 | 
					        let (stop_tx, stop_rx) = oneshot::channel();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -41,21 +40,15 @@ impl FlowySystem {
 | 
				
			|||||||
            sys_cmd_rx,
 | 
					            sys_cmd_rx,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let factory = module_factory();
 | 
					        let module_map = as_module_map(module_factory());
 | 
				
			||||||
        let mut module_map = HashMap::new();
 | 
					        sender_factory(module_map.clone(), &runtime);
 | 
				
			||||||
        factory.into_iter().for_each(|m| {
 | 
					 | 
				
			||||||
            let events = m.events();
 | 
					 | 
				
			||||||
            let rc_module = Rc::new(m);
 | 
					 | 
				
			||||||
            events.into_iter().for_each(|e| {
 | 
					 | 
				
			||||||
                module_map.insert(e, rc_module.clone());
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let system = Self { sys_cmd_tx };
 | 
					        let system = Self { sys_cmd_tx };
 | 
				
			||||||
        sender_factory(Rc::new(module_map), &runtime);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        FlowySystem::set_current(system);
 | 
					        FlowySystem::set_current(system);
 | 
				
			||||||
        let runner = SystemRunner { rt: runtime, stop_rx };
 | 
					        let runner = SystemRunner {
 | 
				
			||||||
 | 
					            rt: runtime,
 | 
				
			||||||
 | 
					            stop_rx,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
        runner
 | 
					        runner
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -107,7 +100,7 @@ impl Future for SystemController {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct SystemRunner {
 | 
					pub struct SystemRunner {
 | 
				
			||||||
    rt: Runtime,
 | 
					    rt: Arc<Runtime>,
 | 
				
			||||||
    stop_rx: oneshot::Receiver<i8>,
 | 
					    stop_rx: oneshot::Receiver<i8>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1 +1,27 @@
 | 
				
			|||||||
 | 
					use std::{io, thread};
 | 
				
			||||||
 | 
					use thread_id;
 | 
				
			||||||
 | 
					use tokio::runtime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub mod ready;
 | 
					pub mod ready;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub(crate) fn tokio_default_runtime() -> io::Result<tokio::runtime::Runtime> {
 | 
				
			||||||
 | 
					    runtime::Builder::new_multi_thread()
 | 
				
			||||||
 | 
					        .thread_name("flowy-sys")
 | 
				
			||||||
 | 
					        .enable_io()
 | 
				
			||||||
 | 
					        .enable_time()
 | 
				
			||||||
 | 
					        .on_thread_start(move || {
 | 
				
			||||||
 | 
					            log::trace!(
 | 
				
			||||||
 | 
					                "{:?} thread started: thread_id= {}",
 | 
				
			||||||
 | 
					                thread::current(),
 | 
				
			||||||
 | 
					                thread_id::get()
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .on_thread_stop(move || {
 | 
				
			||||||
 | 
					            log::trace!(
 | 
				
			||||||
 | 
					                "{:?} thread stopping: thread_id= {}",
 | 
				
			||||||
 | 
					                thread::current(),
 | 
				
			||||||
 | 
					                thread_id::get(),
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .build()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
use flowy_sys::prelude::{EventResponse, FlowySystem, Module, Sender, SenderRequest, SenderRunner};
 | 
					use flowy_sys::prelude::*;
 | 
				
			||||||
use std::{cell::RefCell, sync::Once};
 | 
					use std::{cell::RefCell, sync::Once};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[allow(dead_code)]
 | 
					#[allow(dead_code)]
 | 
				
			||||||
@ -10,44 +10,14 @@ pub fn setup_env() {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
thread_local!(
 | 
					pub async fn async_send(data: DispatchRequest<i64>) -> Result<EventResponse, SystemError> {
 | 
				
			||||||
    static SENDER: RefCell<Option<Sender<i64>>> = RefCell::new(None);
 | 
					    EventDispatch::async_send(data).await
 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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: SenderRequest<i64>) {
 | 
					pub fn init_system<F>(module_factory: F)
 | 
				
			||||||
    SENDER.with(|cell| match &*cell.borrow() {
 | 
					 | 
				
			||||||
        Some(stream) => {
 | 
					 | 
				
			||||||
            stream.async_send(data);
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        None => panic!(""),
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub fn init_system<F>(modules: Vec<Module>, f: F)
 | 
					 | 
				
			||||||
where
 | 
					where
 | 
				
			||||||
    F: FnOnce() + 'static,
 | 
					    F: FnOnce() -> Vec<Module>,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    FlowySystem::construct(
 | 
					    let system = EventDispatch::new(module_factory);
 | 
				
			||||||
        || modules,
 | 
					    EventDispatch::set_current(system);
 | 
				
			||||||
        |module_map, runtime| {
 | 
					 | 
				
			||||||
            let mut sender = Sender::<i64>::new(module_map.clone());
 | 
					 | 
				
			||||||
            runtime.spawn(SenderRunner::new(module_map, sender.take_rx()));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            SENDER.with(|cell| {
 | 
					 | 
				
			||||||
                *cell.borrow_mut() = Some(sender);
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    .spawn(async { f() })
 | 
					 | 
				
			||||||
    .run()
 | 
					 | 
				
			||||||
    .unwrap();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
pub fn stop_system() { FlowySystem::current().stop(); }
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -2,20 +2,14 @@ use crate::helper::*;
 | 
				
			|||||||
use flowy_sys::prelude::*;
 | 
					use flowy_sys::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn hello() -> String { "say hello".to_string() }
 | 
					pub async fn hello() -> String { "say hello".to_string() }
 | 
				
			||||||
#[test]
 | 
					
 | 
				
			||||||
fn test_init() {
 | 
					#[tokio::test]
 | 
				
			||||||
 | 
					async fn test_init() {
 | 
				
			||||||
    setup_env();
 | 
					    setup_env();
 | 
				
			||||||
 | 
					 | 
				
			||||||
    let event = "1";
 | 
					    let event = "1";
 | 
				
			||||||
    let modules = vec![Module::new().event(event, hello)];
 | 
					    init_system(|| vec![Module::new().event(event, hello)]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    init_system(modules, move || {
 | 
					    let request = DispatchRequest::new(1, event);
 | 
				
			||||||
        let request = SenderRequest::new(1, event).callback(|_config, response| {
 | 
					    let resp = async_send(request).await.unwrap();
 | 
				
			||||||
            log::info!("async resp: {:?}", response);
 | 
					    log::info!("sync resp: {:?}", resp);
 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let resp = sync_send(request);
 | 
					 | 
				
			||||||
        log::info!("sync resp: {:?}", resp);
 | 
					 | 
				
			||||||
        stop_system();
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user