cortexfs_channels/
registry.rs1use std::{collections::BTreeMap, fmt, future::Future, sync::Arc};
2
3use crate::{
4 ChannelAdapter, ChannelError, ChannelFuture, ChannelHealth, ChannelId, ChannelStream,
5 DeliveryReceipt, InboundMessage, OutboundMessage,
6};
7
8#[derive(Clone, Default)]
10pub struct ChannelRegistry {
11 adapters: BTreeMap<ChannelId, Arc<dyn ChannelAdapter>>,
12}
13
14impl fmt::Debug for ChannelRegistry {
15 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16 f.debug_struct("ChannelRegistry")
17 .field("ids", &self.ids())
18 .finish()
19 }
20}
21
22impl ChannelRegistry {
23 #[must_use]
24 pub fn new() -> Self {
25 Self::default()
26 }
27
28 pub fn register(&mut self, adapter: Arc<dyn ChannelAdapter>) -> Result<(), ChannelError> {
29 let id = adapter.id();
30 if self.adapters.contains_key(&id) {
31 return Err(ChannelError::DuplicateChannel(id.to_string()));
32 }
33 self.adapters.insert(id, adapter);
34 Ok(())
35 }
36
37 #[must_use]
38 pub fn ids(&self) -> Vec<ChannelId> {
39 self.adapters.keys().cloned().collect()
40 }
41
42 #[must_use]
43 pub fn get(&self, id: &ChannelId) -> Option<Arc<dyn ChannelAdapter>> {
44 self.adapters.get(id).cloned()
45 }
46
47 pub fn listen(&self, id: &ChannelId) -> Result<ChannelStream, ChannelError> {
48 self.get(id)
49 .ok_or_else(|| ChannelError::UnknownChannel(id.to_string()))?
50 .listen()
51 }
52
53 #[must_use]
54 pub fn send(&self, message: OutboundMessage) -> ChannelFuture<'_, DeliveryReceipt> {
55 Box::pin(async move {
56 let id = message.target.channel.clone();
57 let adapter = self
58 .get(&id)
59 .ok_or_else(|| ChannelError::UnknownChannel(id.to_string()))?;
60 adapter.send(message).await
61 })
62 }
63
64 #[must_use]
65 pub fn health(&self, id: &ChannelId) -> ChannelFuture<'_, ChannelHealth> {
66 let id = id.clone();
67 Box::pin(async move {
68 self.get(&id)
69 .ok_or_else(|| ChannelError::UnknownChannel(id.to_string()))?
70 .health()
71 .await
72 })
73 }
74
75 pub fn dispatch<F, Fut>(
76 &self,
77 inbound: InboundMessage,
78 handler: F,
79 ) -> ChannelFuture<'_, DeliveryReceipt>
80 where
81 F: FnOnce(InboundMessage) -> Fut + Send + 'static,
82 Fut: Future<Output = Result<OutboundMessage, ChannelError>> + Send + 'static,
83 {
84 Box::pin(async move { self.send(handler(inbound).await?).await })
85 }
86}