use std::fmt::Debug;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use anyhow::Result;
use async_channel::Sender;
use surrealdb_types::Notification;
#[derive(Clone, Debug)]
pub struct RoutedNotification {
target_node: uuid::Uuid,
notification: Notification,
}
impl RoutedNotification {
pub(crate) fn new(target_node: uuid::Uuid, notification: Notification) -> Self {
Self {
target_node,
notification,
}
}
pub fn target_node_bytes(&self) -> [u8; 16] {
*self.target_node.as_bytes()
}
pub fn into_notification(self) -> Notification {
self.notification
}
}
pub trait NodeEndpointResolver: Send + Sync + Debug {
fn resolve(
&self,
target_node: [u8; 16],
) -> Pin<Box<dyn Future<Output = Option<String>> + Send + '_>>;
}
#[derive(Clone, Debug)]
pub struct BrokerRoutingContext {
pub local_node_id: [u8; 16],
pub endpoint_resolver: Arc<dyn NodeEndpointResolver>,
}
pub trait MessageBroker: Send + Sync + Debug {
fn should_emit(&self, node_id: [u8; 16], target_node: [u8; 16]) -> Result<bool>;
fn send(&self, item: RoutedNotification) -> Pin<Box<dyn Future<Output = ()> + Send + '_>>;
fn attach_routing_context(&self, _ctx: BrokerRoutingContext) {}
}
#[derive(Clone, Debug)]
pub struct LocalMessageBroker(Sender<Notification>);
impl LocalMessageBroker {
pub fn new(channel: Sender<Notification>) -> Arc<Self> {
Arc::new(Self(channel))
}
}
impl MessageBroker for LocalMessageBroker {
fn should_emit(&self, node_id: [u8; 16], target_node: [u8; 16]) -> Result<bool> {
Ok(node_id == target_node)
}
fn send(&self, item: RoutedNotification) -> Pin<Box<dyn Future<Output = ()> + Send + '_>> {
Box::pin(async move {
let _ = self.0.send(item.into_notification()).await;
})
}
}