mecha10-core 0.6.2

Mecha10 core runtime and foundational types
Documentation
//! `StreamBuilder::build`: running the configured filter/map/throttle/debounce/latest pipeline.

use super::StreamBuilder;
use crate::context::Receiver;
use crate::messages::Message;
use std::time::Instant;
use tokio::sync::mpsc;

impl<T: Message + Send + 'static> StreamBuilder<T> {
    /// Build the transformed receiver
    ///
    /// Applies all the configured transformations and returns a new receiver.
    pub fn build(self) -> Receiver<T> {
        let (tx, rx) = mpsc::unbounded_channel();

        tokio::spawn(async move {
            self.run_pipeline(tx).await;
        });

        Receiver::from(rx)
    }

    /// Internal method to run the processing pipeline
    async fn run_pipeline(mut self, tx: mpsc::UnboundedSender<T>) {
        let mut last_send_time = None::<Instant>;
        let mut last_message_time = None::<Instant>;

        while let Some(mut msg) = self.receiver.recv().await {
            let now = Instant::now();

            // Apply filter
            if let Some(ref filter) = self.filter_fn {
                if !filter(&msg) {
                    continue;
                }
            }

            // Apply map transformation
            if let Some(ref mapper) = self.map_fn {
                msg = mapper(msg);
            }

            // Apply debounce - drop messages within debounce window
            if let Some(debounce_dur) = self.debounce_duration {
                if let Some(last_time) = last_message_time {
                    if now.duration_since(last_time) < debounce_dur {
                        // Message arrived too soon, drop it
                        last_message_time = Some(now); // Reset timer
                        continue;
                    }
                }
                last_message_time = Some(now);
            }

            // Apply throttle
            if let Some(throttle_dur) = self.throttle_duration {
                if let Some(last_time) = last_send_time {
                    let elapsed = last_time.elapsed();
                    if elapsed < throttle_dur {
                        continue;
                    }
                }
                last_send_time = Some(Instant::now());
            }

            // Handle latest-only mode
            if self.latest_only {
                // Drain any pending messages
                while self.receiver.try_recv().is_ok() {
                    // Discard old messages
                }
            }

            // Send the message
            if tx.send(msg).is_err() {
                // Receiver dropped, stop processing
                break;
            }
        }
    }
}