use crate::envelope::{e_req_type, e_to_type, Envelope, OneshotErr, ReplyErr};
use crate::error::AskError;
use crate::log_plugin::{LogData, EVENT_LOG};
use crate::main_engine::PluginState;
use crate::registry::Registry;
use ek_event::{Event, EventEngine, PutError};
use std::any::Any;
use std::sync::Arc;
use std::time::Duration;
#[derive(Clone)]
pub struct PluginContext {
pub(crate) event: Arc<EventEngine>,
pub(crate) registry: Arc<Registry>,
pub(crate) name: String,
}
impl PluginContext {
pub(crate) fn new(event: Arc<EventEngine>, registry: Arc<Registry>, name: String) -> Self {
Self { event, registry, name }
}
pub fn name(&self) -> &str {
&self.name
}
pub fn put(&self, event: Event) -> Result<(), PutError> {
self.event.put(event)
}
pub fn write_log(&self, level: u8, msg: &str) {
let data = LogData {
level,
source: self.name.clone(),
msg: msg.to_string(),
};
let _ = self.event.put(Event::with_data(EVENT_LOG, Arc::new(data)));
}
pub fn notify(&self, target: &str, payload: Arc<dyn Any + Send + Sync>) {
let _ = self.event.put(Event::with_data(e_to_type(target), payload));
}
pub fn ask<Req, Res>(&self, target: &str, req: Req, timeout: Duration) -> Result<Res, AskError>
where
Req: Any + Send + Sync,
Res: Any + Send + Sync,
{
match self.registry.get(target) {
Some(entry) if entry.state.get() == PluginState::Running => {}
_ => return Err(AskError::TargetGone { target: target.to_string() }),
}
let (envelope, reply_rx) = Envelope::new(Arc::new(req));
let put = self.event.put(Event::with_data(e_req_type(target), Arc::new(envelope)));
if put.is_err() {
return Err(AskError::BusStopped);
}
let boxed = reply_rx.recv_timeout(timeout).map_err(|e| match e {
OneshotErr::Timeout => AskError::Timeout { target: target.to_string() },
OneshotErr::Closed => AskError::TargetGone { target: target.to_string() },
})?;
match boxed.downcast::<Result<Res, ReplyErr>>() {
Ok(inner) => match *inner {
Ok(res) => Ok(res),
Err(_) => Err(AskError::InvalidPayload { target: target.to_string() }),
},
Err(_) => Err(AskError::InvalidPayload { target: target.to_string() }),
}
}
}