1
0
mirror of https://github.com/actix/examples synced 2024-12-03 18:22:14 +01:00
examples/server-sent-events/src/broadcast.rs

99 lines
2.4 KiB
Rust
Raw Normal View History

2022-02-14 02:37:51 +01:00
use std::{
pin::Pin,
task::{Context, Poll},
time::Duration,
};
use actix_web::{
rt::time::{interval_at, Instant},
web::{Bytes, Data},
Error,
};
use futures_util::Stream;
2022-02-14 02:37:51 +01:00
use parking_lot::Mutex;
use tokio::sync::mpsc::{channel, Receiver, Sender};
2022-02-14 02:37:51 +01:00
pub struct Broadcaster {
inner: Mutex<BroadcasterInner>,
}
struct BroadcasterInner {
2022-02-14 02:37:51 +01:00
clients: Vec<Sender<Bytes>>,
}
impl Broadcaster {
pub fn create() -> Data<Self> {
2022-02-14 02:37:51 +01:00
// Data ~≃ Arc
let me = Data::new(Broadcaster {
inner: Mutex::new(BroadcasterInner {
clients: Vec::new(),
}),
});
2022-02-14 02:37:51 +01:00
// ping clients every 10 seconds to see if they are alive
Broadcaster::spawn_ping(me.clone());
me
}
fn spawn_ping(me: Data<Self>) {
2022-02-14 02:37:51 +01:00
actix_web::rt::spawn(async move {
let mut interval = interval_at(Instant::now(), Duration::from_secs(10));
2022-02-14 02:37:51 +01:00
loop {
interval.tick().await;
me.remove_stale_clients();
2022-02-14 02:37:51 +01:00
}
});
}
fn remove_stale_clients(&self) {
let mut inner = self.inner.lock();
2022-02-14 02:37:51 +01:00
let mut ok_clients = Vec::new();
for client in inner.clients.iter() {
2022-02-14 02:37:51 +01:00
let result = client.clone().try_send(Bytes::from("data: ping\n\n"));
if let Ok(()) = result {
ok_clients.push(client.clone());
}
}
inner.clients = ok_clients;
2022-02-14 02:37:51 +01:00
}
pub fn new_client(&self) -> Client {
2022-02-14 02:37:51 +01:00
let (tx, rx) = channel(100);
tx.try_send(Bytes::from("data: connected\n\n")).unwrap();
let mut inner = self.inner.lock();
inner.clients.push(tx);
2022-02-14 02:37:51 +01:00
Client(rx)
}
pub fn send(&self, msg: &str) {
let msg = Bytes::from(["data: ", msg, "\n\n"].concat());
let inner = self.inner.lock();
for client in inner.clients.iter() {
2022-02-14 02:37:51 +01:00
client.clone().try_send(msg.clone()).unwrap_or(());
}
}
}
// wrap Receiver in own type, with correct error type
pub struct Client(Receiver<Bytes>);
2022-02-14 02:37:51 +01:00
impl Stream for Client {
type Item = Result<Bytes, Error>;
2022-02-18 03:44:02 +01:00
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
match Pin::new(&mut self.0).poll_recv(cx) {
2022-02-14 02:37:51 +01:00
Poll::Ready(Some(v)) => Poll::Ready(Some(Ok(v))),
Poll::Ready(None) => Poll::Ready(None),
Poll::Pending => Poll::Pending,
}
}
}