use matter_codec::Value;
use matter_interaction::{AttributePath, EventReport};
use tokio::sync::mpsc;
use crate::actor::Command;
use crate::error::Error;
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
pub struct AttributeReport {
pub path: AttributePath,
pub value: Value,
}
#[derive(Debug)]
#[non_exhaustive]
pub enum SubscriptionEvent {
Report(AttributeReport),
Event(EventReport),
Established {
subscription_id: u32,
},
Resubscribing {
cause: Error,
},
Lagged {
dropped: usize,
},
}
pub(crate) const SUBSCRIPTION_CHANNEL_CAP: usize = 256;
pub struct Subscription {
pub(crate) rx: mpsc::Receiver<SubscriptionEvent>,
pub(crate) ctrl_rx: mpsc::UnboundedReceiver<SubscriptionEvent>,
pub(crate) tx: mpsc::Sender<Command>,
pub(crate) key: crate::actor::SubId,
pub(crate) cancelled: bool,
}
impl Subscription {
pub async fn next(&mut self) -> Option<SubscriptionEvent> {
tokio::select! {
biased;
ctrl = self.ctrl_rx.recv() => {
match ctrl {
Some(ev) => Some(ev),
None => self.rx.recv().await,
}
}
report = self.rx.recv() => {
match report {
Some(ev) => Some(ev),
None => self.ctrl_rx.recv().await,
}
}
}
}
pub async fn cancel(mut self) -> Result<(), Error> {
self.cancelled = true;
self.tx
.send(Command::CancelSubscription { key: self.key })
.await
.map_err(|_| Error::ControllerStopped)
}
}
impl Drop for Subscription {
fn drop(&mut self) {
if !self.cancelled {
let _ = self
.tx
.try_send(Command::CancelSubscription { key: self.key });
}
}
}