use super::{MessageQueue, QueueReceiver};
use crate::Result;
use async_trait::async_trait;
use tokio::sync::broadcast;
pub struct MemoryQueue {
tx: broadcast::Sender<Vec<u8>>,
}
impl MemoryQueue {
pub fn new() -> Self {
Self::with_capacity(1024)
}
pub fn with_capacity(cap: usize) -> Self {
let (tx, _rx) = broadcast::channel(cap);
MemoryQueue { tx }
}
}
impl Default for MemoryQueue {
fn default() -> Self {
MemoryQueue::new()
}
}
#[async_trait]
impl MessageQueue for MemoryQueue {
async fn publish(&self, payload: &[u8]) -> Result<()> {
let _ = self.tx.send(payload.to_vec());
Ok(())
}
async fn subscribe(&self) -> Result<Box<dyn QueueReceiver>> {
Ok(Box::new(MemoryReceiver {
rx: self.tx.subscribe(),
}))
}
}
struct MemoryReceiver {
rx: broadcast::Receiver<Vec<u8>>,
}
#[async_trait]
impl QueueReceiver for MemoryReceiver {
async fn recv(&mut self) -> Option<Vec<u8>> {
loop {
match self.rx.recv().await {
Ok(v) => return Some(v),
Err(broadcast::error::RecvError::Lagged(_)) => continue,
Err(broadcast::error::RecvError::Closed) => return None,
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn publishes_to_subscriber() {
let q = MemoryQueue::new();
let mut sub = q.subscribe().await.unwrap();
q.publish(b"hello").await.unwrap();
assert_eq!(sub.recv().await, Some(b"hello".to_vec()));
}
}