rainier_broadcast/
manager.rs1use std::sync::Arc;
4
5use serde_json::Value;
6
7use rainier_support::Result;
8
9use crate::broadcaster::{Broadcaster, LogBroadcaster};
10use crate::channel::Channel;
11use crate::event::{Broadcast, Broadcastable};
12
13pub struct Broadcasting {
18 driver: Arc<dyn Broadcaster>,
19}
20
21impl Broadcasting {
22 pub fn new(driver: Arc<dyn Broadcaster>) -> Self {
24 Self { driver }
25 }
26
27 pub fn log() -> Self {
30 Self::new(Arc::new(LogBroadcaster))
31 }
32
33 pub fn driver_name(&self) -> &'static str {
35 self.driver.name()
36 }
37
38 pub fn driver(&self) -> &Arc<dyn Broadcaster> {
40 &self.driver
41 }
42
43 pub async fn event<E: Broadcastable + ?Sized>(&self, event: &E) -> Result<()> {
48 if !event.broadcast_when() {
49 return Ok(());
50 }
51 self.send(Broadcast::of(event)?).await
52 }
53
54 pub async fn event_except<E: Broadcastable + ?Sized>(
60 &self,
61 event: &E,
62 socket_id: Option<String>,
63 ) -> Result<()> {
64 if !event.broadcast_when() {
65 return Ok(());
66 }
67 self.send(Broadcast::of(event)?.except_maybe(socket_id)).await
68 }
69
70 pub async fn to(
75 &self,
76 channels: Vec<Channel>,
77 event: impl Into<String>,
78 payload: Value,
79 ) -> Result<()> {
80 self.send(Broadcast::new(event, channels, payload)).await
81 }
82
83 pub async fn send(&self, broadcast: Broadcast) -> Result<()> {
85 if broadcast.is_empty() {
88 return Ok(());
89 }
90 self.driver.publish(&broadcast).await
91 }
92}
93
94impl std::fmt::Debug for Broadcasting {
95 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96 f.debug_struct("Broadcasting").field("driver", &self.driver.name()).finish()
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103 use crate::broadcaster::MemoryBroadcaster;
104 use serde::Serialize;
105
106 #[derive(Serialize)]
107 struct Ping {
108 room: u64,
109 #[serde(skip)]
110 visible: bool,
111 }
112
113 impl Broadcastable for Ping {
114 fn broadcast_on(&self) -> Vec<Channel> {
115 vec![Channel::private(format!("room.{}", self.room))]
116 }
117 fn broadcast_when(&self) -> bool {
118 self.visible
119 }
120 }
121
122 fn manager() -> (Broadcasting, Arc<MemoryBroadcaster>) {
123 let driver = Arc::new(MemoryBroadcaster::new());
124 (Broadcasting::new(driver.clone()), driver)
125 }
126
127 #[tokio::test]
128 async fn an_event_reaches_the_driver() {
129 let (broadcasting, driver) = manager();
130
131 broadcasting.event(&Ping { room: 1, visible: true }).await.unwrap();
132
133 driver.assert_broadcast("Ping", "private-room.1");
134 }
135
136 #[tokio::test]
137 async fn broadcast_when_false_sends_nothing() {
138 let (broadcasting, driver) = manager();
139
140 broadcasting.event(&Ping { room: 1, visible: false }).await.unwrap();
141
142 driver.assert_nothing_broadcast();
143 }
144
145 #[tokio::test]
146 async fn to_others_carries_the_socket_to_skip() {
147 let (broadcasting, driver) = manager();
148
149 broadcasting
150 .event_except(&Ping { room: 1, visible: true }, Some("1234.5678".into()))
151 .await
152 .unwrap();
153
154 assert_eq!(driver.sent()[0].except.as_deref(), Some("1234.5678"));
155 }
156
157 #[tokio::test]
158 async fn a_request_with_no_socket_header_broadcasts_to_everyone() {
159 let (broadcasting, driver) = manager();
160
161 broadcasting.event_except(&Ping { room: 1, visible: true }, None).await.unwrap();
162
163 assert_eq!(driver.sent()[0].except, None);
164 }
165
166 #[tokio::test]
167 async fn an_event_with_no_channels_never_reaches_the_driver() {
168 let (broadcasting, driver) = manager();
169
170 broadcasting.to(vec![], "manual", serde_json::json!({ "a": 1 })).await.unwrap();
171
172 driver.assert_nothing_broadcast();
173 }
174}