AppFlowy/rust-lib/flowy-sys/src/rt/system.rs

168 lines
4.7 KiB
Rust
Raw Normal View History

2021-06-26 15:52:03 +00:00
use crate::{
2021-06-27 07:11:41 +00:00
module::{Event, Module},
request::EventRequest,
response::EventResponse,
rt::runtime::Runtime,
2021-06-26 15:52:03 +00:00
};
2021-06-27 07:11:41 +00:00
use futures_core::{ready, task::Context};
use crate::error::{InternalError, SystemError};
2021-06-26 17:24:00 +00:00
use std::{cell::RefCell, collections::HashMap, future::Future, io, sync::Arc};
2021-06-26 15:52:03 +00:00
use tokio::{
macros::support::{Pin, Poll},
sync::{
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
oneshot,
},
};
thread_local!(
static CURRENT: RefCell<Option<Arc<FlowySystem>>> = RefCell::new(None);
);
2021-06-27 14:07:33 +00:00
#[derive(Debug)]
pub enum SystemCommand {
2021-06-27 07:11:41 +00:00
Exit(i8),
2021-06-27 14:07:33 +00:00
EventResponse(EventResponse),
2021-06-27 07:11:41 +00:00
}
2021-06-26 15:52:03 +00:00
pub struct FlowySystem {
2021-06-27 07:11:41 +00:00
sys_tx: UnboundedSender<SystemCommand>,
forward_map: HashMap<Event, UnboundedSender<EventRequest>>,
2021-06-26 15:52:03 +00:00
}
impl FlowySystem {
2021-06-27 14:07:33 +00:00
pub fn construct<F>(module_factory: F, response_tx: Option<UnboundedSender<EventResponse>>) -> SystemRunner
2021-06-26 15:52:03 +00:00
where
2021-06-27 14:07:33 +00:00
F: FnOnce(UnboundedSender<SystemCommand>) -> Vec<Module>,
2021-06-26 15:52:03 +00:00
{
let runtime = Runtime::new().unwrap();
2021-06-27 07:11:41 +00:00
let (sys_tx, sys_rx) = unbounded_channel::<SystemCommand>();
2021-06-26 15:52:03 +00:00
let (stop_tx, stop_rx) = oneshot::channel();
2021-06-27 07:11:41 +00:00
runtime.spawn(SystemController {
stop_tx: Some(stop_tx),
sys_rx,
2021-06-27 14:07:33 +00:00
response_tx,
2021-06-27 07:11:41 +00:00
});
2021-06-26 15:52:03 +00:00
let mut system = Self {
2021-06-27 14:07:33 +00:00
sys_tx: sys_tx.clone(),
2021-06-27 07:11:41 +00:00
forward_map: HashMap::default(),
2021-06-26 15:52:03 +00:00
};
2021-06-27 14:07:33 +00:00
let factory = module_factory(sys_tx.clone());
2021-06-26 15:52:03 +00:00
factory.into_iter().for_each(|m| {
2021-06-27 07:11:41 +00:00
system.forward_map.extend(m.forward_map());
2021-06-26 15:52:03 +00:00
runtime.spawn(m);
});
FlowySystem::set_current(system);
let runner = SystemRunner { rt: runtime, stop_rx };
runner
}
2021-06-27 07:11:41 +00:00
pub fn sink(&self, event: Event, request: EventRequest) -> Result<(), SystemError> {
2021-06-27 14:07:33 +00:00
log::debug!("Sink event: {}", event);
2021-06-27 07:11:41 +00:00
let _ = self.forward_map.get(&event)?.send(request)?;
Ok(())
}
2021-06-27 14:07:33 +00:00
pub fn request_tx(&self, event: Event) -> Option<UnboundedSender<EventRequest>> {
match self.forward_map.get(&event) {
Some(tx) => Some(tx.clone()),
None => None,
}
}
2021-06-27 07:11:41 +00:00
pub fn stop(&self) {
match self.sys_tx.send(SystemCommand::Exit(0)) {
Ok(_) => {},
Err(e) => {
log::error!("Stop system error: {}", e);
},
2021-06-26 17:24:00 +00:00
}
2021-06-26 15:52:03 +00:00
}
#[doc(hidden)]
pub fn set_current(sys: FlowySystem) {
CURRENT.with(|cell| {
*cell.borrow_mut() = Some(Arc::new(sys));
})
}
pub fn current() -> Arc<FlowySystem> {
CURRENT.with(|cell| match *cell.borrow() {
Some(ref sys) => sys.clone(),
None => panic!("System is not running"),
})
}
2021-06-27 07:11:41 +00:00
}
2021-06-26 15:52:03 +00:00
struct SystemController {
2021-06-27 07:11:41 +00:00
stop_tx: Option<oneshot::Sender<i8>>,
sys_rx: UnboundedReceiver<SystemCommand>,
2021-06-27 14:07:33 +00:00
response_tx: Option<UnboundedSender<EventResponse>>,
2021-06-26 15:52:03 +00:00
}
impl Future for SystemController {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
loop {
2021-06-27 07:11:41 +00:00
match ready!(Pin::new(&mut self.sys_rx).poll_recv(cx)) {
2021-06-26 15:52:03 +00:00
None => return Poll::Ready(()),
2021-06-27 07:11:41 +00:00
Some(cmd) => match cmd {
SystemCommand::Exit(code) => {
if let Some(tx) = self.stop_tx.take() {
let _ = tx.send(code);
}
},
2021-06-27 14:07:33 +00:00
SystemCommand::EventResponse(resp) => {
log::debug!("Response: {:?}", resp);
if let Some(tx) = &self.response_tx {
match tx.send(resp) {
Ok(_) => {},
Err(e) => {
log::error!("Response tx send fail: {:?}", e);
},
}
}
},
2021-06-26 15:52:03 +00:00
},
}
}
}
}
pub struct SystemRunner {
rt: Runtime,
2021-06-27 07:11:41 +00:00
stop_rx: oneshot::Receiver<i8>,
2021-06-26 15:52:03 +00:00
}
impl SystemRunner {
pub fn run(self) -> io::Result<()> {
let SystemRunner { rt, stop_rx } = self;
match rt.block_on(stop_rx) {
Ok(code) => {
if code != 0 {
Err(io::Error::new(
io::ErrorKind::Other,
format!("Non-zero exit code: {}", code),
))
} else {
Ok(())
}
},
Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)),
}
}
pub fn spawn<F>(self, future: F) -> Self
where
F: Future<Output = ()> + 'static,
{
self.rt.spawn(future);
self
}
}