1use crate::envelope::{e_req_type, e_to_type, Envelope, OneshotErr, ReplyErr};
13use crate::error::AskError;
14use crate::lifecycle::{EVENT_SRV_CHG, EVENT_SRV_CHG_PREFIX};
15use crate::main_engine::{PluginInfo, PluginState};
16use crate::registry::Registry;
17use crate::service::{ProviderRef, ServiceDesc};
18use ek_event::{Event, EventEngine, PutError};
19use std::any::{Any, type_name};
20use std::sync::Arc;
21use std::time::Duration;
22
23#[derive(Clone)]
25pub struct PluginContext {
26 pub(crate) event: Arc<EventEngine>,
27 pub(crate) registry: Arc<Registry>,
28 pub(crate) name: String,
29}
30
31impl PluginContext {
32 pub(crate) fn new(event: Arc<EventEngine>, registry: Arc<Registry>, name: String) -> Self {
33 Self { event, registry, name }
34 }
35
36 pub fn name(&self) -> &str {
38 &self.name
39 }
40
41 pub fn put(&self, event: Event) -> Result<(), PutError> {
46 self.event.put(event)
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 plugins(&self) -> Vec<PluginInfo> {
58 let mut out = Vec::new();
59 for name in self.registry.names() {
60 if let Some(info) = self.registry.info_of(&name) {
61 out.push(info);
62 }
63 }
64 out
65 }
66
67 pub fn services_of(&self, name: &str) -> Option<Arc<Vec<ServiceDesc>>> {
71 self.registry.services_of(name)
72 }
73
74 pub fn find_service(&self, svc: &str) -> Vec<ProviderRef> {
77 let mut out = Vec::new();
78 for name in self.registry.index_providers(svc) {
79 let Some(list) = self.registry.services_of(&name) else { continue };
80 let Some(entry) = self.registry.get(&name) else { continue };
81 if let Some(desc) = list.iter().find(|d| d.id == svc) {
82 out.push(ProviderRef {
83 name: entry.name.clone(),
84 version: entry.plugin.version().into_owned(),
85 state: entry.state.get(),
86 service: desc.clone(),
87 });
88 }
89 }
90 out
91 }
92
93 pub fn publish_services(&self, list: Vec<ServiceDesc>) {
101 let name = self.name.clone();
102 let version = self.registry.publish(&name, list);
103 let _ = self
104 .event
105 .put(Event::with_data(format!("{EVENT_SRV_CHG_PREFIX}{name}"), Arc::new(version.clone())));
106 let _ = self
107 .event
108 .put(Event::with_data(EVENT_SRV_CHG, Arc::new(crate::service::PlugNotice { name, version })));
109 }
110
111 pub fn ask<Req, Res>(&self, target: &str, req: Req, timeout: Duration) -> Result<Res, AskError>
126 where
127 Req: Any + Send + Sync,
128 Res: Any + Send + Sync,
129 {
130 match self.registry.get(target) {
131 Some(entry) if entry.state.get() == PluginState::Running => {}
132 _ => return Err(AskError::TargetGone { target: target.to_string() }),
133 }
134 self.deliver(target, req, timeout)
135 }
136
137 pub fn ask_service<Req, Res>(&self, svc: &str, req: Req, timeout: Duration) -> Result<Res, AskError>
146 where
147 Req: Any + Send + Sync,
148 Res: Any + Send + Sync,
149 {
150 let providers = self.find_service(svc);
151 if providers.is_empty() {
152 return Err(AskError::UnknownService { service: svc.to_string() });
153 }
154 let Some(slot) = providers.iter().find(|p| p.state == PluginState::Running) else {
155 return Err(AskError::TargetGone { target: providers[0].name.clone() });
156 };
157 if slot.service.req_type != type_name::<Req>() {
158 return Err(AskError::InvalidPayload { target: slot.name.clone() });
159 }
160 self.deliver(&slot.name.clone(), req, timeout)
161 }
162
163 fn deliver<Req, Res>(&self, target: &str, req: Req, timeout: Duration) -> Result<Res, AskError>
165 where
166 Req: Any + Send + Sync,
167 Res: Any + Send + Sync,
168 {
169 let (envelope, reply_rx) = Envelope::new(Arc::new(req));
170 let put = self.event.put(Event::with_data(e_req_type(target), Arc::new(envelope)));
171 if put.is_err() {
172 return Err(AskError::BusStopped);
173 }
174 let boxed = reply_rx.recv_timeout(timeout).map_err(|e| match e {
175 OneshotErr::Timeout => AskError::Timeout { target: target.to_string() },
176 OneshotErr::Closed => AskError::TargetGone { target: target.to_string() },
177 })?;
178 match boxed.downcast::<Result<Res, ReplyErr>>() {
180 Ok(inner) => match *inner {
181 Ok(res) => Ok(res),
182 Err(_) => Err(AskError::InvalidPayload { target: target.to_string() }),
183 },
184 Err(_) => Err(AskError::InvalidPayload { target: target.to_string() }),
186 }
187 }
188}