|
1 | 1 | use futures::future::BoxFuture; |
2 | 2 | use futures::FutureExt; |
3 | | -use tokio::sync::broadcast::error::SendError; |
4 | 3 | use tokio::sync::broadcast::{self}; |
5 | 4 |
|
6 | | -use crate::sender::Sender; |
| 5 | +use crate::receiver::{Receiver, RecvError}; |
| 6 | +use crate::sender::{SendError, Sender}; |
7 | 7 |
|
8 | 8 | const CHANNEL_CAPACITY: usize = 32768; |
9 | 9 |
|
10 | | -/// An event sender implementation using a broadcast channel. |
11 | | -#[derive(Clone)] |
12 | | -pub struct Broadcaster<E: Sync + Send + Clone> { |
13 | | - pub(crate) sender: broadcast::Sender<E>, |
| 10 | +/// An event sender and receiver implementation using a broadcast channel. |
| 11 | +#[derive(Clone, Debug)] |
| 12 | +pub struct Broadcaster<Event: Sync + Send + Clone> { |
| 13 | + pub(crate) sender: broadcast::Sender<Event>, |
14 | 14 | } |
15 | 15 |
|
16 | | -impl<E: Sync + Send + Clone> Sender for Broadcaster<E> { |
17 | | - type Event = E; |
18 | | - |
19 | | - fn send_event(&self, event: E) -> BoxFuture<'_, Option<Result<usize, SendError<E>>>> { |
20 | | - async move { Some(self.sender.send(event)) }.boxed() |
21 | | - } |
22 | | -} |
23 | | - |
24 | | -impl<E: Sync + Send + Clone> Default for Broadcaster<E> { |
| 16 | +impl<Event: Sync + Send + Clone> Default for Broadcaster<Event> { |
25 | 17 | fn default() -> Self { |
26 | | - let (sender, _) = broadcast::channel(CHANNEL_CAPACITY); |
| 18 | + let (sender, _receiver) = broadcast::channel(CHANNEL_CAPACITY); |
27 | 19 | Self { sender } |
28 | 20 | } |
29 | 21 | } |
30 | 22 |
|
31 | | -impl<E: Sync + Send + Clone> Broadcaster<E> { |
| 23 | +impl<Event: Sync + Send + Clone> Broadcaster<Event> { |
32 | 24 | #[must_use] |
33 | | - pub fn subscribe(&self) -> broadcast::Receiver<E> { |
| 25 | + pub fn subscribe(&self) -> broadcast::Receiver<Event> { |
34 | 26 | self.sender.subscribe() |
35 | 27 | } |
36 | 28 | } |
| 29 | + |
| 30 | +impl<Event: Sync + Send + Clone> Sender for Broadcaster<Event> { |
| 31 | + type Event = Event; |
| 32 | + |
| 33 | + fn send(&self, event: Event) -> BoxFuture<'_, Option<Result<usize, SendError<Event>>>> { |
| 34 | + async move { Some(self.sender.send(event).map_err(std::convert::Into::into)) }.boxed() |
| 35 | + } |
| 36 | +} |
| 37 | + |
| 38 | +impl<Event: Sync + Send + Clone> Receiver for broadcast::Receiver<Event> { |
| 39 | + type Event = Event; |
| 40 | + |
| 41 | + fn recv(&mut self) -> BoxFuture<'_, Result<Self::Event, RecvError>> { |
| 42 | + async move { self.recv().await.map_err(std::convert::Into::into) }.boxed() |
| 43 | + } |
| 44 | +} |
| 45 | + |
| 46 | +impl<Event> From<broadcast::error::SendError<Event>> for SendError<Event> { |
| 47 | + fn from(err: broadcast::error::SendError<Event>) -> Self { |
| 48 | + SendError(err.0) |
| 49 | + } |
| 50 | +} |
| 51 | + |
| 52 | +impl From<broadcast::error::RecvError> for RecvError { |
| 53 | + fn from(err: broadcast::error::RecvError) -> Self { |
| 54 | + match err { |
| 55 | + broadcast::error::RecvError::Lagged(amt) => RecvError::Lagged(amt), |
| 56 | + broadcast::error::RecvError::Closed => RecvError::Closed, |
| 57 | + } |
| 58 | + } |
| 59 | +} |
| 60 | + |
| 61 | +#[cfg(test)] |
| 62 | +mod tests { |
| 63 | + use tokio::time::{timeout, Duration}; |
| 64 | + |
| 65 | + use super::*; |
| 66 | + |
| 67 | + #[tokio::test] |
| 68 | + async fn it_should_allow_sending_an_event_and_received_it() { |
| 69 | + let broadcaster = Broadcaster::<String>::default(); |
| 70 | + |
| 71 | + let mut receiver = broadcaster.subscribe(); |
| 72 | + |
| 73 | + let event = "test"; |
| 74 | + |
| 75 | + let _unused = broadcaster.send(event.to_owned()).await.unwrap().unwrap(); |
| 76 | + |
| 77 | + let received_event = receiver.recv().await.unwrap(); |
| 78 | + |
| 79 | + assert_eq!(received_event, event); |
| 80 | + } |
| 81 | + |
| 82 | + #[tokio::test] |
| 83 | + async fn it_should_return_the_number_of_receivers_when_and_event_is_sent() { |
| 84 | + let broadcaster = Broadcaster::<String>::default(); |
| 85 | + let mut _receiver = broadcaster.subscribe(); |
| 86 | + |
| 87 | + let number_of_receivers = broadcaster.send("test".into()).await; |
| 88 | + |
| 89 | + assert!(matches!(number_of_receivers, Some(Ok(1)))); |
| 90 | + } |
| 91 | + |
| 92 | + #[tokio::test] |
| 93 | + async fn it_should_fail_when_trying_tos_send_with_no_subscribers() { |
| 94 | + let event = String::from("test"); |
| 95 | + |
| 96 | + let broadcaster = Broadcaster::<String>::default(); |
| 97 | + |
| 98 | + let result: Result<usize, SendError<String>> = broadcaster.send(event).await.unwrap(); |
| 99 | + |
| 100 | + assert!(matches!(result, Err(SendError::<String>(_event)))); |
| 101 | + } |
| 102 | + |
| 103 | + #[tokio::test] |
| 104 | + async fn it_should_allow_subscribing_multiple_receivers() { |
| 105 | + let broadcaster = Broadcaster::<u8>::default(); |
| 106 | + let mut r1 = broadcaster.subscribe(); |
| 107 | + let mut r2 = broadcaster.subscribe(); |
| 108 | + |
| 109 | + let _ = broadcaster.send(1).await; |
| 110 | + |
| 111 | + let val1 = timeout(Duration::from_secs(1), r1.recv()).await.unwrap().unwrap(); |
| 112 | + let val2 = timeout(Duration::from_secs(1), r2.recv()).await.unwrap().unwrap(); |
| 113 | + |
| 114 | + assert_eq!(val1, 1); |
| 115 | + assert_eq!(val2, 1); |
| 116 | + } |
| 117 | +} |
0 commit comments