use crate::error::TransportError;
use alopex_chirps_wire::frame::Frame;
use alopex_chirps_wire::node_id::NodeId;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::net::SocketAddr;
use tokio::sync::mpsc;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum BackendProfile {
Control,
Ephemeral,
Durable,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct BackendCapabilities {
pub control: bool,
pub ephemeral: bool,
pub durable: bool,
}
impl Default for BackendCapabilities {
fn default() -> Self {
Self {
control: true,
ephemeral: true,
durable: false,
}
}
}
impl BackendCapabilities {
pub fn supports(self, profile: BackendProfile) -> bool {
match profile {
BackendProfile::Control => self.control,
BackendProfile::Ephemeral => self.ephemeral,
BackendProfile::Durable => self.durable,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
pub struct EnvelopeMetadata {
pub message_id: Option<[u8; 16]>,
pub sequence: Option<u64>,
pub partition: Option<u64>,
pub acknowledgement: Option<u64>,
pub replay: bool,
pub checkpoint: Option<u64>,
pub offset: Option<u64>,
}
#[async_trait]
pub trait MessageBackend: Send + Sync {
fn capabilities(&self) -> BackendCapabilities {
BackendCapabilities::default()
}
async fn send(&self, target: NodeId, frame: Frame) -> Result<(), TransportError>;
async fn send_with_profile(
&self,
target: NodeId,
frame: Frame,
profile: BackendProfile,
_metadata: EnvelopeMetadata,
) -> Result<(), TransportError> {
if !self.capabilities().supports(profile) || profile == BackendProfile::Durable {
return Err(TransportError::NotImplemented(
"requested message profile is not supported by this backend",
));
}
self.send(target, frame).await
}
async fn broadcast(&self, frame: Frame) -> Result<usize, TransportError>;
async fn broadcast_with_profile(
&self,
frame: Frame,
profile: BackendProfile,
_metadata: EnvelopeMetadata,
) -> Result<usize, TransportError> {
if !self.capabilities().supports(profile) || profile == BackendProfile::Durable {
return Err(TransportError::NotImplemented(
"requested message profile is not supported by this backend",
));
}
self.broadcast(frame).await
}
async fn subscribe(&self) -> Result<mpsc::Receiver<(NodeId, Frame)>, TransportError>;
async fn close(&self) -> Result<(), TransportError>;
fn connected_peers(&self) -> Vec<(NodeId, SocketAddr)>;
}