opendeviationbar-streaming 13.79.0

Real-time streaming engine for open deviation bar processing
Documentation
//! LiveBarSource: thin adapter over LiveBarEngine (Issue #178, Phase 1)

use async_trait::async_trait;
use std::time::Duration;

use super::traits::{BarSource, SourceCheckpoint};
use crate::live_engine::{CompletedBar, LiveBarEngine};

/// Wraps the existing `LiveBarEngine` as a `BarSource`.
/// Thin adapter (~30 LOC) — delegates all behavior to the engine.
pub struct LiveBarSource {
    engine: LiveBarEngine,
}

impl LiveBarSource {
    pub fn new(engine: LiveBarEngine) -> Self {
        Self { engine }
    }

    /// Access the underlying engine for start/stop/metrics.
    pub fn engine_mut(&mut self) -> &mut LiveBarEngine {
        &mut self.engine
    }

    /// Access the underlying engine (immutable).
    pub fn engine(&self) -> &LiveBarEngine {
        &self.engine
    }
}

#[async_trait]
impl BarSource for LiveBarSource {
    async fn next_bar(&mut self, timeout: Duration) -> Option<CompletedBar> {
        self.engine.next_bar(timeout).await
    }

    fn snapshot(&self) -> Option<SourceCheckpoint> {
        // LiveBarEngine doesn't expose a simple snapshot — checkpoint collection
        // requires async. Return None; OdbEngine uses collect_checkpoints() on shutdown.
        None
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::live_engine::LiveEngineConfig;
    use std::collections::HashMap;

    #[test]
    fn test_live_bar_source_creation() {
        let mut sym_thresholds: HashMap<String, Vec<u32>> = HashMap::new();
        sym_thresholds.insert("BTCUSDT".into(), vec![250]);
        let config = LiveEngineConfig::new(sym_thresholds);
        let engine = LiveBarEngine::new(config);
        let source = LiveBarSource::new(engine);
        assert!(!source.engine().is_started());
    }
}