use std::{
convert::Infallible,
pin::Pin,
task::{ready, Context, Poll},
};
use async_channel::bounded;
use http_kit::{http_error, utils::Stream};
use pin_project_lite::pin_project;
use super::{Event, Sse};
pub const DEFAULT_CHANNEL_CAPACITY: usize = 16;
#[derive(Debug, Clone)]
pub struct Sender {
sender: async_channel::Sender<Event>,
}
http_error!(
pub SendError, http_kit::StatusCode::INTERNAL_SERVER_ERROR, "Failed to send event to SSE channel");
pin_project! {
struct Receiver{
#[pin]
receiver:async_channel::Receiver<Event>,
}
}
impl Receiver {
pub const fn new(receiver: async_channel::Receiver<Event>) -> Self {
Self { receiver }
}
}
impl Stream for Receiver {
type Item = Result<Event, Infallible>;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
Poll::Ready(ready!(self.project().receiver.poll_next(cx)).map(Ok))
}
}
impl Sender {
pub(crate) fn new() -> (Self, Sse) {
Self::with_capacity(DEFAULT_CHANNEL_CAPACITY)
}
pub(crate) fn with_capacity(capacity: usize) -> (Self, Sse) {
let (sender, receiver) = bounded(capacity);
(Self { sender }, Sse::from_stream(Receiver::new(receiver)))
}
pub async fn send(&self, event: Event) -> Result<(), SendError> {
self.sender.send(event).await.map_err(|_| SendError::new())
}
pub async fn send_data(&self, data: impl AsRef<str>) -> Result<(), SendError> {
self.send(Event::data(data)).await
}
}