Skip to main content

harmont_cli/orchestrator/
output_subscriber.rs

1//! Build-event subscriber that passes events to an [`OutputRenderer`].
2//!
3//! Replaces the plan-2 plugin-based output subscriber with a simple
4//! loop that calls [`OutputRenderer::on_event`] for each bus event.
5
6// Pedantic-bucket nags accepted at module scope:
7// - `needless_pass_by_value` on `bus`: the owned `Arc<EventBus>` makes
8//   the bus->subscriber handoff explicit at the call site.
9#![allow(clippy::needless_pass_by_value)]
10
11use std::sync::Arc;
12
13use tokio::sync::broadcast::error::RecvError;
14
15use super::events::EventBus;
16use crate::runner::OutputRenderer;
17
18/// Spawn the subscriber task. Returns a join handle the orchestrator
19/// awaits at shutdown so the `BuildEnd` event is fully drained.
20#[must_use]
21pub fn spawn(
22    bus: Arc<EventBus>,
23    mut renderer: Box<dyn OutputRenderer>,
24) -> tokio::task::JoinHandle<()> {
25    let mut rx = bus.subscribe();
26    tokio::spawn(async move {
27        loop {
28            match rx.recv().await {
29                Ok(event) => {
30                    let is_end = event.is_build_end();
31                    renderer.on_event(&event);
32                    if is_end {
33                        return;
34                    }
35                }
36                Err(RecvError::Closed) => return,
37                Err(RecvError::Lagged(n)) => {
38                    tracing::warn!("output: dropped {n} events");
39                }
40            }
41        }
42    })
43}