enable module data passed in

This commit is contained in:
appflowy 2021-07-09 17:47:15 +08:00
parent 2b137738ea
commit 13e52ae350
5 changed files with 65 additions and 97 deletions

View File

@ -49,7 +49,7 @@ impl EventDispatch {
let dispatch = dispatch.as_ref().unwrap();
let module_map = dispatch.module_map.clone();
let service = Box::new(DispatchService { module_map });
log::trace!("Async event: {:?}", &request.event());
log::trace!("Async event: {:?}", &request.event);
let service_ctx = DispatchContext {
request,
callback: Some(Box::new(callback)),
@ -142,7 +142,7 @@ impl Service<DispatchContext> for DispatchService {
Box::pin(async move {
let result = {
match module_map.get(&request.event()) {
match module_map.get(&request.event) {
Some(module) => {
let fut = module.new_service(());
let service_fut = fut.await?.call(request);

View File

@ -3,15 +3,15 @@ use std::{
collections::HashMap,
};
#[derive(Default)]
pub struct DataContainer {
#[derive(Default, Debug)]
pub struct ModuleDataMap {
map: HashMap<TypeId, Box<dyn Any + Sync + Send>>,
}
impl DataContainer {
impl ModuleDataMap {
#[inline]
pub fn new() -> DataContainer {
DataContainer {
pub fn new() -> ModuleDataMap {
ModuleDataMap {
map: HashMap::default(),
}
}
@ -57,71 +57,9 @@ impl DataContainer {
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: ModuleDataMap) { self.map.extend(other.map); }
}
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)
// }

View File

@ -1,9 +1,9 @@
use crate::{
error::SystemError,
error::{InternalError, SystemError},
request::{payload::Payload, EventRequest, FromRequest},
util::ready::Ready,
util::ready::{ready, Ready},
};
use std::{ops::Deref, sync::Arc};
use std::{any::type_name, ops::Deref, sync::Arc};
pub struct ModuleData<T: ?Sized + Send + Sync>(Arc<T>);
@ -47,5 +47,13 @@ where
type Future = Ready<Result<Self, SystemError>>;
#[inline]
fn from_request(_req: &EventRequest, _: &mut Payload) -> Self::Future { unimplemented!() }
fn from_request(req: &EventRequest, _: &mut Payload) -> Self::Future {
if let Some(data) = req.module_data::<ModuleData<T>>() {
ready(Ok(data.clone()))
} else {
let msg = format!("Failed to get the module data(type: {})", type_name::<T>());
log::error!("{}", msg,);
ready(Err(InternalError::new(msg).into()))
}
}
}

View File

@ -13,7 +13,7 @@ use pin_project::pin_project;
use crate::{
error::{InternalError, SystemError},
module::{container::DataContainer, ModuleData},
module::{container::ModuleDataMap, ModuleData},
request::{payload::Payload, EventRequest, FromRequest},
response::{EventResponse, Responder},
service::{
@ -55,7 +55,7 @@ pub type EventServiceFactory = BoxServiceFactory<(), ServiceRequest, ServiceResp
pub struct Module {
pub name: String,
module_data: DataContainer,
module_data: Arc<ModuleDataMap>,
service_map: Arc<HashMap<Event, EventServiceFactory>>,
}
@ -63,7 +63,7 @@ impl Module {
pub fn new() -> Self {
Self {
name: "".to_owned(),
module_data: DataContainer::new(),
module_data: Arc::new(ModuleDataMap::new()),
service_map: Arc::new(HashMap::new()),
}
}
@ -74,7 +74,10 @@ impl Module {
}
pub fn data<D: 'static + Send + Sync>(mut self, data: D) -> Self {
self.module_data.insert(ModuleData::new(data));
Arc::get_mut(&mut self.module_data)
.unwrap()
.insert(ModuleData::new(data));
self
}
@ -108,8 +111,9 @@ impl Module {
#[derive(Debug)]
pub struct ModuleRequest {
inner: EventRequest,
payload: Payload,
pub(crate) id: String,
pub(crate) event: Event,
pub(crate) payload: Payload,
}
impl ModuleRequest {
@ -118,7 +122,8 @@ impl ModuleRequest {
E: Into<Event>,
{
Self {
inner: EventRequest::new(event, uuid::Uuid::new_v4().to_string()),
id: uuid::Uuid::new_v4().to_string(),
event: event.into(),
payload: Payload::None,
}
}
@ -130,22 +135,14 @@ impl ModuleRequest {
self.payload = payload.into();
self
}
pub fn id(&self) -> &str { &self.inner.id }
pub fn event(&self) -> &Event { &self.inner.event }
}
impl std::fmt::Display for ModuleRequest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{:?}", self.inner.id, self.inner.event)
write!(f, "{}:{:?}", self.id, self.event)
}
}
impl std::convert::Into<ServiceRequest> for ModuleRequest {
fn into(self) -> ServiceRequest { ServiceRequest::new(self.inner, self.payload) }
}
impl ServiceFactory<ModuleRequest> for Module {
type Response = EventResponse;
type Error = SystemError;
@ -155,8 +152,12 @@ impl ServiceFactory<ModuleRequest> for Module {
fn new_service(&self, _cfg: Self::Context) -> Self::Future {
let service_map = self.service_map.clone();
let module_data = self.module_data.clone();
Box::pin(async move {
let service = ModuleService { service_map };
let service = ModuleService {
service_map,
module_data,
};
let module_service = Box::new(service) as Self::Service;
Ok(module_service)
})
@ -165,6 +166,7 @@ impl ServiceFactory<ModuleRequest> for Module {
pub struct ModuleService {
service_map: Arc<HashMap<Event, EventServiceFactory>>,
module_data: Arc<ModuleDataMap>,
}
impl Service<ModuleRequest> for ModuleService {
@ -173,13 +175,18 @@ impl Service<ModuleRequest> for ModuleService {
type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
fn call(&self, request: ModuleRequest) -> Self::Future {
match self.service_map.get(&request.event()) {
let ModuleRequest { id, event, payload } = request;
let module_data = self.module_data.clone();
let request = EventRequest::new(id.clone(), event, module_data);
match self.service_map.get(&request.event) {
Some(factory) => {
let service_fut = factory.new_service(());
let fut = ModuleServiceFuture {
fut: Box::pin(async {
let service = service_fut.await?;
service.call(request.into()).await
let service_req = ServiceRequest::new(request, payload);
service.call(service_req).await
}),
};
Box::pin(async move { Ok(fut.await.unwrap_or_else(|e| e.into())) })

View File

@ -2,34 +2,49 @@ use std::future::Future;
use crate::{
error::{InternalError, SystemError},
module::Event,
module::{Event, ModuleDataMap},
request::payload::Payload,
util::ready::{ready, Ready},
};
use derivative::*;
use futures_core::ready;
use std::{
fmt::Debug,
pin::Pin,
sync::Arc,
task::{Context, Poll},
};
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Derivative)]
pub struct EventRequest {
pub(crate) id: String,
pub(crate) event: Event,
#[derivative(Debug = "ignore")]
pub(crate) module_data: Arc<ModuleDataMap>,
}
impl EventRequest {
pub fn new<E>(event: E, id: String) -> EventRequest
pub fn new<E>(id: String, event: E, module_data: Arc<ModuleDataMap>) -> EventRequest
where
E: Into<Event>,
{
Self {
id,
event: event.into(),
module_data,
}
}
pub fn module_data<T: 'static>(&self) -> Option<&T>
where
T: Send + Sync,
{
if let Some(data) = self.module_data.get::<T>() {
return Some(data);
}
None
}
}
pub trait FromRequest: Sized {