use crate::fact::Fact;
use tokio::sync::{broadcast, mpsc};
pub type FactSender = mpsc::UnboundedSender<Fact>;
pub type FactReceiver = mpsc::UnboundedReceiver<Fact>;
pub type EventSender = broadcast::Sender<Fact>;
pub type EventReceiver = broadcast::Receiver<Fact>;
const EVENT_CHANNEL_CAPACITY: usize = 1024;
pub struct ChannelPair {
pub command_tx: FactSender,
pub command_rx: FactReceiver,
pub event_tx: EventSender,
pub event_rx: EventReceiver,
}
impl ChannelPair {
pub fn new() -> Self {
let (command_tx, command_rx) = mpsc::unbounded_channel();
let (event_tx, event_rx) = broadcast::channel(EVENT_CHANNEL_CAPACITY);
Self {
command_tx,
command_rx,
event_tx,
event_rx,
}
}
}
impl Default for ChannelPair {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used)]
use super::*;
use crate::fact::FactId;
use evorule_tcb::JsonValue;
#[tokio::test]
async fn test_command_channel_fifo_order() {
let mut pair = ChannelPair::new();
pair.command_tx
.send(Fact::Command {
id: FactId(1),
instruction: JsonValue::empty_object(),
})
.unwrap();
pair.command_tx
.send(Fact::Command {
id: FactId(2),
instruction: JsonValue::empty_object(),
})
.unwrap();
pair.command_tx
.send(Fact::Command {
id: FactId(3),
instruction: JsonValue::empty_object(),
})
.unwrap();
let f1 = pair.command_rx.recv().await.unwrap();
let f2 = pair.command_rx.recv().await.unwrap();
let f3 = pair.command_rx.recv().await.unwrap();
assert_eq!(f1.id(), FactId(1));
assert_eq!(f2.id(), FactId(2));
assert_eq!(f3.id(), FactId(3));
}
#[test]
fn test_command_sender_clone() {
let pair = ChannelPair::new();
let tx_clone = pair.command_tx.clone();
tx_clone
.send(Fact::Stable {
id: FactId(1),
version: 0,
})
.unwrap();
pair.command_tx
.send(Fact::Stable {
id: FactId(2),
version: 0,
})
.unwrap();
}
#[tokio::test]
async fn test_event_broadcast_multiple_subscribers() {
let mut pair = ChannelPair::new();
let mut rx2 = pair.event_tx.subscribe();
pair.event_tx
.send(Fact::Stable {
id: FactId(1),
version: 0,
})
.unwrap();
let f1 = pair.event_rx.recv().await.unwrap();
let f2 = rx2.recv().await.unwrap();
assert_eq!(f1.id(), FactId(1));
assert_eq!(f2.id(), FactId(1));
}
}