222 lines
6.9 KiB
Rust
Raw Normal View History

use crate::{
errors::{DispatchError, InternalError},
module::{container::AFPluginStateMap, AFPluginState},
request::{payload::Payload, AFPluginEventRequest, FromAFPluginRequest},
2022-12-01 10:59:22 +08:00
response::{AFPluginEventResponse, AFPluginResponder},
service::{
factory, AFPluginHandler, AFPluginHandlerService, AFPluginServiceFactory, BoxService, BoxServiceFactory,
Service, ServiceRequest, ServiceResponse,
},
};
use futures_core::future::BoxFuture;
use futures_core::ready;
use nanoid::nanoid;
use pin_project::pin_project;
use std::sync::Arc;
2021-06-25 23:53:13 +08:00
use std::{
collections::HashMap,
2021-07-03 14:14:10 +08:00
fmt,
fmt::{Debug, Display},
2021-06-25 23:53:13 +08:00
future::Future,
hash::Hash,
2021-06-25 23:53:13 +08:00
pin::Pin,
task::{Context, Poll},
};
pub type AFPluginMap = Arc<HashMap<AFPluginEvent, Arc<AFPlugin>>>;
pub(crate) fn as_plugin_map(plugins: Vec<AFPlugin>) -> AFPluginMap {
let mut plugin_map = HashMap::new();
plugins.into_iter().for_each(|m| {
let events = m.events();
let plugins = Arc::new(m);
events.into_iter().for_each(|e| {
plugin_map.insert(e, plugins.clone());
});
});
Arc::new(plugin_map)
}
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
pub struct AFPluginEvent(String);
impl<T: Display + Eq + Hash + Debug + Clone> std::convert::From<T> for AFPluginEvent {
2022-01-23 12:14:00 +08:00
fn from(t: T) -> Self {
AFPluginEvent(format!("{}", t))
2022-01-23 12:14:00 +08:00
}
}
2022-12-01 10:59:22 +08:00
/// A plugin is used to handle the events that the plugin can handle.
///
/// When an event is a dispatched by the `AFPluginDispatcher`, the dispatcher will
/// find the corresponding plugin to handle the event. The name of the event must be unique,
/// which means only one handler will get called.
///
pub struct AFPlugin {
2021-07-03 14:14:10 +08:00
pub name: String,
2022-12-01 10:59:22 +08:00
/// a list of `AFPluginState` that the plugin registers. The state can be read by the plugin's handler.
states: Arc<AFPluginStateMap>,
2022-12-01 10:59:22 +08:00
/// Contains a list of factories that are used to generate the services used to handle the passed-in
/// `ServiceRequest`.
///
event_service_factory:
Arc<HashMap<AFPluginEvent, BoxServiceFactory<(), ServiceRequest, ServiceResponse, DispatchError>>>,
2021-06-25 23:53:13 +08:00
}
impl std::default::Default for AFPlugin {
2021-11-27 19:19:41 +08:00
fn default() -> Self {
2021-06-25 23:53:13 +08:00
Self {
name: "".to_owned(),
states: Arc::new(AFPluginStateMap::new()),
event_service_factory: Arc::new(HashMap::new()),
2021-06-25 23:53:13 +08:00
}
}
2021-11-27 19:19:41 +08:00
}
impl AFPlugin {
2022-01-23 12:14:00 +08:00
pub fn new() -> Self {
AFPlugin::default()
2022-01-23 12:14:00 +08:00
}
2021-06-25 23:53:13 +08:00
pub fn name(mut self, s: &str) -> Self {
self.name = s.to_owned();
self
}
pub fn state<D: 'static + Send + Sync>(mut self, data: D) -> Self {
Arc::get_mut(&mut self.states).unwrap().insert(AFPluginState::new(data));
2021-07-09 17:47:15 +08:00
2021-06-25 23:53:13 +08:00
self
}
pub fn event<E, H, T, R>(mut self, event: E, handler: H) -> Self
2021-06-25 23:53:13 +08:00
where
H: AFPluginHandler<T, R>,
T: FromAFPluginRequest + 'static + Send + Sync,
<T as FromAFPluginRequest>::Future: Sync + Send,
R: Future + 'static + Send + Sync,
R::Output: AFPluginResponder + 'static,
E: Eq + Hash + Debug + Clone + Display,
2021-06-25 23:53:13 +08:00
{
let event: AFPluginEvent = event.into();
if self.event_service_factory.contains_key(&event) {
2022-12-01 10:59:22 +08:00
panic!("Register duplicate Event: {:?}", &event);
} else {
Arc::get_mut(&mut self.event_service_factory)
.unwrap()
.insert(event, factory(AFPluginHandlerService::new(handler)));
2021-06-27 15:11:41 +08:00
}
2021-06-25 23:53:13 +08:00
self
}
2021-06-26 23:52:03 +08:00
pub fn events(&self) -> Vec<AFPluginEvent> {
self.event_service_factory.keys().cloned().collect::<Vec<_>>()
2022-01-23 12:14:00 +08:00
}
2021-06-25 23:53:13 +08:00
}
2022-12-01 10:59:22 +08:00
/// A request that will be passed to the corresponding plugin.
///
/// Each request can carry the payload that will be deserialized into the corresponding data struct.
///
2021-09-04 15:12:53 +08:00
#[derive(Debug, Clone)]
pub struct AFPluginRequest {
pub id: String,
pub event: AFPluginEvent,
2021-07-09 17:47:15 +08:00
pub(crate) payload: Payload,
}
impl AFPluginRequest {
pub fn new<E>(event: E) -> Self
where
E: Into<AFPluginEvent>,
{
Self {
2022-04-11 15:27:03 +08:00
id: nanoid!(6),
2021-07-09 17:47:15 +08:00
event: event.into(),
payload: Payload::None,
}
}
pub fn payload<P>(mut self, payload: P) -> Self
where
P: Into<Payload>,
{
self.payload = payload.into();
self
}
}
impl std::fmt::Display for AFPluginRequest {
2022-01-23 12:14:00 +08:00
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{:?}", self.id, self.event)
}
2021-07-03 14:14:10 +08:00
}
impl AFPluginServiceFactory<AFPluginRequest> for AFPlugin {
2022-12-01 10:59:22 +08:00
type Response = AFPluginEventResponse;
type Error = DispatchError;
type Service = BoxService<AFPluginRequest, Self::Response, Self::Error>;
type Context = ();
type Future = BoxFuture<'static, Result<Self::Service, Self::Error>>;
2021-06-27 22:07:33 +08:00
fn new_service(&self, _cfg: Self::Context) -> Self::Future {
let services = self.event_service_factory.clone();
let states = self.states.clone();
2021-06-27 22:07:33 +08:00
Box::pin(async move {
let service = AFPluginService { services, states };
Ok(Box::new(service) as Self::Service)
2021-06-27 22:07:33 +08:00
})
}
}
pub struct AFPluginService {
services: Arc<HashMap<AFPluginEvent, BoxServiceFactory<(), ServiceRequest, ServiceResponse, DispatchError>>>,
states: Arc<AFPluginStateMap>,
2021-06-27 22:07:33 +08:00
}
impl Service<AFPluginRequest> for AFPluginService {
2022-12-01 10:59:22 +08:00
type Response = AFPluginEventResponse;
type Error = DispatchError;
type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
2021-06-27 22:07:33 +08:00
fn call(&self, request: AFPluginRequest) -> Self::Future {
let AFPluginRequest { id, event, payload } = request;
let states = self.states.clone();
let request = AFPluginEventRequest::new(id, event, states);
2021-07-09 17:47:15 +08:00
match self.services.get(&request.event) {
2021-06-27 22:07:33 +08:00
Some(factory) => {
let service_fut = factory.new_service(());
let fut = AFPluginServiceFuture {
fut: Box::pin(async {
let service = service_fut.await?;
2021-07-09 17:47:15 +08:00
let service_req = ServiceRequest::new(request, payload);
service.call(service_req).await
}),
2021-06-27 22:07:33 +08:00
};
2021-06-28 14:27:16 +08:00
Box::pin(async move { Ok(fut.await.unwrap_or_else(|e| e.into())) })
2022-01-23 12:14:00 +08:00
}
None => {
2021-09-04 15:12:53 +08:00
let msg = format!("Can not find service factory for event: {:?}", request.event);
Box::pin(async { Err(InternalError::ServiceNotFound(msg).into()) })
2022-01-23 12:14:00 +08:00
}
2021-06-27 22:07:33 +08:00
}
}
}
2021-06-26 23:52:03 +08:00
#[pin_project]
pub struct AFPluginServiceFuture {
2021-06-25 23:53:13 +08:00
#[pin]
fut: BoxFuture<'static, Result<ServiceResponse, DispatchError>>,
2021-06-25 23:53:13 +08:00
}
impl Future for AFPluginServiceFuture {
2022-12-01 10:59:22 +08:00
type Output = Result<AFPluginEventResponse, DispatchError>;
2021-06-25 23:53:13 +08:00
2021-06-26 23:52:03 +08:00
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
2021-11-27 19:19:41 +08:00
let (_, response) = ready!(self.as_mut().project().fut.poll(cx))?.into_parts();
Poll::Ready(Ok(response))
2021-06-26 23:52:03 +08:00
}
2021-06-25 23:53:13 +08:00
}