1use crate::envelope::{e_req_type, e_to_type, Envelope, OneshotErr, ReplyErr};
7use crate::error::AskError;
8use crate::log_plugin::{LogData, EVENT_LOG};
9use crate::main_engine::PluginState;
10use crate::registry::Registry;
11use ek_event::{Event, EventEngine, PutError};
12use std::any::Any;
13use std::sync::Arc;
14use std::time::Duration;
15
16#[derive(Clone)]
18pub struct PluginContext {
19 pub(crate) event: Arc<EventEngine>,
20 pub(crate) registry: Arc<Registry>,
21 pub(crate) name: String,
22}
23
24impl PluginContext {
25 pub(crate) fn new(event: Arc<EventEngine>, registry: Arc<Registry>, name: String) -> Self {
26 Self { event, registry, name }
27 }
28
29 pub fn name(&self) -> &str {
31 &self.name
32 }
33
34 pub fn put(&self, event: Event) -> Result<(), PutError> {
36 self.event.put(event)
37 }
38
39 pub fn write_log(&self, level: u8, msg: &str) {
41 let data = LogData {
42 level,
43 source: self.name.clone(),
44 msg: msg.to_string(),
45 };
46 let _ = self.event.put(Event::with_data(EVENT_LOG, Arc::new(data)));
47 }
48
49 pub fn notify(&self, target: &str, payload: Arc<dyn Any + Send + Sync>) {
51 let _ = self.event.put(Event::with_data(e_to_type(target), payload));
52 }
53
54 pub fn ask<Req, Res>(&self, target: &str, req: Req, timeout: Duration) -> Result<Res, AskError>
72 where
73 Req: Any + Send + Sync,
74 Res: Any + Send + Sync,
75 {
76 match self.registry.get(target) {
77 Some(entry) if entry.state.get() == PluginState::Running => {}
78 _ => return Err(AskError::TargetGone { target: target.to_string() }),
79 }
80 let (envelope, reply_rx) = Envelope::new(Arc::new(req));
81 let put = self.event.put(Event::with_data(e_req_type(target), Arc::new(envelope)));
82 if put.is_err() {
83 return Err(AskError::BusStopped);
84 }
85 let boxed = reply_rx.recv_timeout(timeout).map_err(|e| match e {
86 OneshotErr::Timeout => AskError::Timeout { target: target.to_string() },
87 OneshotErr::Closed => AskError::TargetGone { target: target.to_string() },
88 })?;
89 match boxed.downcast::<Result<Res, ReplyErr>>() {
91 Ok(inner) => match *inner {
92 Ok(res) => Ok(res),
93 Err(_) => Err(AskError::InvalidPayload { target: target.to_string() }),
94 },
95 Err(_) => Err(AskError::InvalidPayload { target: target.to_string() }),
97 }
98 }
99}