Expand description
Build and run typed task graphs.
Tasks connect TaskNode implementations into a small execution graph. Each node receives a
typed input, produces a typed output, and hands control to the next step through a
Transition.
The main entry points are:
Taskto define and run a graphTransitionto describe how execution should continue after a node finishesTask::register_node_fnfor lightweight synchronous closure nodesNodeIdhelpers such asNodeId::transitions_withandNodeId::joinfor the common next-step and join casesTransition::fan_outfor typed static fan-out branches
§Examples
A small linear task:
use swiftide_tasks::{NodeError, Task, TaskRunOutcome};
let mut task = Task::<i32, i32>::new();
let start = task.register_node_fn(|input: &i32| -> Result<i32, NodeError> { Ok(*input + 1) });
let finish =
task.register_node_fn(|input: &i32| -> Result<i32, NodeError> { Ok(*input * 2) });
task.starts_with(start);
task.register_transition(start, move |value| finish.transitions_with(value))?;
task.register_transition(finish, task.transitions_to_finish())?;
let result = task.run(2).await?;
assert_eq!(result, TaskRunOutcome::Completed(6));A fan-out with an explicit join:
use swiftide_tasks::{JoinInput, NodeError, Task, TaskRunOutcome, Transition};
let mut task = Task::<i32, i32>::new();
let start = task.register_node_fn(|input: &i32| -> Result<i32, NodeError> { Ok(*input) });
let double =
task.register_node_fn(|input: &i32| -> Result<i32, NodeError> { Ok(*input * 2) });
let increment =
task.register_node_fn(|input: &i32| -> Result<i32, NodeError> { Ok(*input + 1) });
let join = task.register_node_fn(|input: &JoinInput<i32>| -> Result<i32, NodeError> {
Ok(input.iter().copied().sum())
});
task.starts_with(start);
task.register_transition(start, move |value| {
// `join_with` defines the branch group and the join node that waits for it.
Transition::fan_out(&double, value)
.and(&increment, value)
.join_with(join.join())
})?;
// Branches still decide where their own output goes before the join can run. Fan-out branches
// cannot finish independently; use a join node as the single place that finishes the task.
task.register_transition(double, join.join())?;
task.register_transition(increment, join.join())?;
task.register_transition(join, task.transitions_to_finish())?;
let result = task.run(3).await?;
assert_eq!(result, TaskRunOutcome::Completed(10));Structs§
- AnyJoin
Input - The type-erased aggregated view of branches that have reached a join node.
- AnyJoin
Target - A configured join destination for branches with mixed payload types.
- AsyncFn
- Wraps an asynchronous closure and exposes it as a
TaskNode. - FanOut
Transition - A typed fan-out transition builder that must be connected to a join before it can run.
- Join
Input - The typed aggregated view of branches that have reached a join node.
- Join
Target - A configured join destination for branches that should converge into a join node.
- Mapped
Join Target - A join target with a synchronous payload mapping step.
- Marked
Transition - A linear transition that preserves the destination node type.
- Node
Error - Wraps an error produced by a specific node execution.
- NodeId
- A typed handle to a registered node in a
Task. - SyncFn
- Wraps a synchronous closure and exposes it as a
TaskNode. - Task
- A typed task graph that can run sequential, branching, and joining workflows.
- Transition
- Describes how task execution should continue after a node completes.
Enums§
- Concurrency
Model - Controls whether newly scheduled work should run one branch at a time or concurrently.
- Current
Nodes - The currently active task nodes that match a requested node type.
- Task
Error - Errors returned while defining, running, or resuming a task.
- Task
RunOutcome - The observable outcome of calling
Task::runorTask::resume.