Skip to main content

actionqueue_workflow/
children.rs

1//! Dispatch-time snapshot building for child task states.
2//!
3//! The re-exported types from `actionqueue-executor-local` are the canonical
4//! snapshot types; this module provides the builder that queries the projection
5//! to construct them.
6
7use actionqueue_core::ids::TaskId;
8pub use actionqueue_executor_local::children::{ChildState, ChildrenSnapshot};
9use actionqueue_storage::recovery::reducer::ReplayReducer;
10
11/// Builds a [`ChildrenSnapshot`] by querying the projection for all tasks
12/// whose `parent_task_id` matches `parent_id`.
13///
14/// Returns `None` if there are no children (avoids allocating an empty snapshot).
15/// Returns `Some(snapshot)` with all child run states at the current projection
16/// sequence — this is an immutable point-in-time view safe to pass to handlers
17/// running on `spawn_blocking`.
18pub fn build_children_snapshot(
19    projection: &ReplayReducer,
20    parent_id: TaskId,
21) -> Option<ChildrenSnapshot> {
22    let children: Vec<ChildState> = projection
23        .task_records()
24        .filter(|tr| tr.task_spec().parent_task_id() == Some(parent_id))
25        .map(|tr| {
26            let child_id = tr.task_spec().id();
27            let run_states: Vec<_> = projection
28                .run_instances()
29                .filter(|r| r.task_id() == child_id)
30                .map(|r| (r.id(), r.state()))
31                .collect();
32            ChildState::new(child_id, run_states)
33        })
34        .collect();
35
36    if children.is_empty() {
37        None
38    } else {
39        Some(ChildrenSnapshot::new(children))
40    }
41}