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

Task Grouping and Hierarchical Cancellation

You will define logical scopes for task batches to simplify resource teardown.

In this lesson, you will learn how to structure concurrent workloads into logical batches that share a common lifecycle, ensuring that if one task fails, the entire group cleans up gracefully.

Defining Task Scopes

In complex systems, firing off dozens of background tasks can lead to "orphan" processes if the parent crashes or if the work is no longer needed. Task grouping allows you to fence off a set of operations into a single scope. Instead of managing individual JoinHandle objects, you treat the entire batch as a unit of work.

Hierarchical Cancellation

The core power of this pattern is hierarchical cancellation. By organizing tasks into a tree-like structure, we create a chain of responsibility. If a parent scope is cancelled—due to a timeout, a user aborting a request, or an unrecoverable error—the signal propagates downwards, automatically triggering the cancellation of all child tasks.

Consider this conceptual structure using a task group:

async fn process_user_request(data: Data) -> Result<(), Error> {
    // We open a group scope. Everything inside is tied to this context.
    task_group::scope(|group| {
        group.spawn(fetch_database_record(data.id));
        group.spawn(compute_analytics(data.payload));
        
        // If either task fails or the scope is dropped, 
        // the remaining task is immediately cancelled.
    }).await
}

By grouping these tasks, you avoid the "leaking" of background work. If fetch_database_record fails, the task_group context detects the failure, cancels the compute_analytics task, and ensures that resources—like file handles or network sockets held by those tasks—are dropped properly as the tasks unwind.

This approach transforms complex manual cleanup logic into a declarative guarantee. You are no longer responsible for "cleaning up" each individual thread or async task; instead, you define the boundary of the work, and the runtime handles the teardown automatically when that boundary is breached. This is the foundation for building resilient systems that handle failures locally without crashing the entire application.

Key Takeaway: Hierarchical cancellation treats groups of concurrent tasks as a single lifecycle, ensuring that failures or cancellations propagate down the tree to automatically clean up all associated resources.