use std::num::NonZeroUsize;
use std::sync::Arc;
use std::time::Duration;
use futures::Stream;
use ruststream::{BatchSubscriber, BufferedSubscriber, Subscriber};
use tokio::sync::mpsc;
use crate::broker::Link;
use crate::conn::Shared;
use crate::error::MqttError;
use crate::message::MqttMessage;
pub(crate) const BATCH_MAX_WAIT: Duration = Duration::from_millis(20);
#[derive(Clone, Copy, Debug)]
pub(crate) enum OnDrop {
Unsubscribe,
Keep,
}
struct WireSubscriber {
id: u64,
shared: Arc<Shared>,
link: Link,
on_drop: OnDrop,
rx: mpsc::UnboundedReceiver<Result<MqttMessage, MqttError>>,
}
impl std::fmt::Debug for WireSubscriber {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("WireSubscriber").finish_non_exhaustive()
}
}
impl Drop for WireSubscriber {
fn drop(&mut self) {
match self.on_drop {
OnDrop::Unsubscribe => self.shared.release(self.id, &self.link),
OnDrop::Keep => self.shared.leave(self.id),
}
}
}
impl Subscriber for WireSubscriber {
type Message = MqttMessage;
type Error = MqttError;
fn stream(&mut self) -> impl Stream<Item = Result<MqttMessage, MqttError>> + Send + '_ {
futures::stream::poll_fn(move |cx| self.rx.poll_recv(cx))
}
}
pub struct MqttSubscriber {
filter: String,
buffered: BufferedSubscriber<WireSubscriber>,
}
impl std::fmt::Debug for MqttSubscriber {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MqttSubscriber")
.field("filter", &self.filter)
.finish_non_exhaustive()
}
}
impl MqttSubscriber {
pub(crate) fn new(
filter: String,
id: u64,
shared: Arc<Shared>,
link: Link,
on_drop: OnDrop,
rx: mpsc::UnboundedReceiver<Result<MqttMessage, MqttError>>,
) -> Self {
Self {
filter,
buffered: BufferedSubscriber::new(WireSubscriber {
id,
shared,
link,
on_drop,
rx,
})
.max_wait(BATCH_MAX_WAIT),
}
}
#[must_use]
pub fn filter(&self) -> &str {
&self.filter
}
}
impl Subscriber for MqttSubscriber {
type Message = MqttMessage;
type Error = MqttError;
fn stream(&mut self) -> impl Stream<Item = Result<MqttMessage, MqttError>> + Send + '_ {
self.buffered.stream()
}
}
impl BatchSubscriber for MqttSubscriber {
type Batch = Vec<MqttMessage>;
fn batches(
&mut self,
size: NonZeroUsize,
) -> impl Stream<Item = Result<Self::Batch, MqttError>> + Send + '_ {
self.buffered.batches(size)
}
}