Skip to main content

cuenv_task_graph/
resolver.rs

1//! Task resolution abstractions for group expansion.
2//!
3//! This module provides the [`TaskResolution`] enum and [`TaskResolver`] trait
4//! that enable unified handling of single tasks and task groups (sequential/parallel).
5
6use crate::TaskNodeData;
7
8/// How a task name resolves - single task or group.
9///
10/// This enum represents the three ways a task name can resolve:
11/// - A single leaf task (no children)
12/// - A sequential group (children run in order)
13/// - A parallel group (children run concurrently)
14#[derive(Debug, Clone)]
15pub enum TaskResolution<T: TaskNodeData> {
16    /// A single leaf task with its data.
17    Single(T),
18
19    /// Sequential group - tasks run in order (implicit deps between them).
20    ///
21    /// Children are named like `"build[0]"`, `"build[1]"` for a group named `"build"`.
22    Sequential {
23        /// Child task names in execution order.
24        children: Vec<String>,
25    },
26
27    /// Parallel group - tasks can run concurrently.
28    ///
29    /// Children are named like `"build.frontend"`, `"build.backend"` for a group named `"build"`.
30    Parallel {
31        /// Child task names (no particular order).
32        children: Vec<String>,
33        /// Group-level dependencies applied to all children.
34        depends_on: Vec<String>,
35    },
36}
37
38/// Trait for resolving task names to their definitions.
39///
40/// Implement this trait to provide task lookup and group expansion
41/// for use with [`TaskGraph::build_for_task_with_resolver`].
42///
43/// # Example
44///
45/// ```ignore
46/// impl TaskResolver<Task> for Tasks {
47///     fn resolve(&self, name: &str) -> Option<TaskResolution<Task>> {
48///         let definition = self.get(name)?;
49///         match definition {
50///             TaskDefinition::Single(task) => Some(TaskResolution::Single(task.clone())),
51///             TaskDefinition::Group(TaskGroup::Sequential(tasks)) => {
52///                 let children = (0..tasks.len())
53///                     .map(|i| format!("{}[{}]", name, i))
54///                     .collect();
55///                 Some(TaskResolution::Sequential { children })
56///             }
57///             // ... parallel handling
58///         }
59///     }
60/// }
61/// ```
62pub trait TaskResolver<T: TaskNodeData> {
63    /// Resolve a task name to its definition (single or group).
64    ///
65    /// Returns `None` if the task doesn't exist.
66    fn resolve(&self, name: &str) -> Option<TaskResolution<T>>;
67}