Course contentsShow
← Rust
Lesson 1230 of 1,91010. Concurrency PrimitivesFree lesson

Concurrent Stream Aggregation

You will collect results from diverse asynchronous streams into a single output.

In this lesson, you will learn how to unify multiple asynchronous data sources into a single, cohesive stream using concurrent aggregation.

The Concept of Aggregation

When working with asynchronous Rust, you often encounter scenarios where data arrives from multiple independent sources—such as different microservices, sensors, or user inputs. Instead of processing these streams sequentially or managing complex manual polling, Concurrent Stream Aggregation allows you to merge these disparate "rivers" into one stream. This enables you to process items as they arrive, regardless of which source produced them.

Practical Implementation

In the futures ecosystem, we achieve this using the StreamExt::merge trait method. This creates a new stream that polls all input streams concurrently and yields items from whichever stream is ready first.

Consider an example where we collect heartbeats from two different network nodes:

use futures::stream::{self, StreamExt};

async fn aggregate_heartbeats() {
    let node_a = stream::iter(vec!["A1", "A2"]);
    let node_b = stream::iter(vec!["B1", "B2"]);

    // Merge both streams into one
    let mut combined = stream::select(node_a, node_b);

    while let Some(msg) = combined.next().await {
        println!("Received signal: {}", msg);
    }
}

Why it Matters

The power of this approach lies in its non-blocking nature. By aggregating streams, your task doesn't get stuck waiting for a slow sensor if a fast sensor has already provided data. This is fundamentally different from collecting data into a Vec and then iterating, which would require waiting for the entire batch to arrive.

Aggregation is the glue that connects real-time inputs into a unified pipeline, ensuring your application remains responsive even as the number of data sources scales. Because this happens at the Stream level, the runtime handles the underlying task waking and scheduling, keeping your code clean and memory-efficient.

Key Takeaway: Concurrent stream aggregation transforms fragmented, asynchronous inputs into a single, ordered flow, allowing your system to process events with maximum concurrency as they occur.