Skip to main content

viser_encoding/
progress.rs

1use std::sync::atomic::{AtomicI64, Ordering};
2use tokio::sync::mpsc;
3use tracing::debug;
4
5/// Non-blocking progress sender. Logs when updates are dropped due to a full channel.
6pub struct ProgressSender<T> {
7    tx: Option<mpsc::Sender<T>>,
8    dropped: AtomicI64,
9}
10
11impl<T> ProgressSender<T> {
12    pub fn new(tx: Option<mpsc::Sender<T>>) -> Self {
13        Self { tx, dropped: AtomicI64::new(0) }
14    }
15
16    /// Attempts to send a progress update. Non-blocking.
17    pub fn send(&self, value: T) {
18        let Some(ref tx) = self.tx else { return };
19        match tx.try_send(value) {
20            Ok(()) => {}
21            Err(mpsc::error::TrySendError::Full(_)) => {
22                let count = self.dropped.fetch_add(1, Ordering::Relaxed) + 1;
23                if count == 1 || count % 100 == 0 {
24                    debug!("progress update dropped (channel full), total_dropped={count}");
25                }
26            }
27            Err(mpsc::error::TrySendError::Closed(_)) => {}
28        }
29    }
30
31    pub fn dropped(&self) -> i64 {
32        self.dropped.load(Ordering::Relaxed)
33    }
34}