pub struct Task<Input: NodeArg, Output: NodeArg> { /* private fields */ }Expand description
A typed task graph that can run sequential, branching, and joining workflows.
Register nodes with Task::register_node or Task::register_node_fn, choose a start node
with Task::starts_with, connect nodes with Task::register_transition, and then execute
the task with Task::run.
The task value stores runtime state as well as the graph definition, so reuse the same task when you need pause and resume behavior. Clone a task when you want a fresh runtime with the same graph definition.
§Examples
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 * 3) });
task.starts_with(start);
task.register_transition(start, move |value| finish.transitions_with(value))?;
task.register_transition(finish, task.transitions_to_finish())?;
assert_eq!(task.run(2).await?, TaskRunOutcome::Completed(9));Implementations§
Source§impl<Input: NodeArg + Clone, Output: NodeArg + Clone> Task<Input, Output>
impl<Input: NodeArg + Clone, Output: NodeArg + Clone> Task<Input, Output>
Sourcepub fn with_default_concurrency_model(
self,
default_concurrency_model: ConcurrencyModel,
) -> Self
pub fn with_default_concurrency_model( self, default_concurrency_model: ConcurrencyModel, ) -> Self
Sets the default concurrency model for transitions that do not override it explicitly.
§Examples
use swiftide_tasks::{ConcurrencyModel, Task};
let task = Task::<i32, i32>::new()
.with_default_concurrency_model(ConcurrencyModel::Parallel);
let _ = task;Sourcepub fn starts_with<T: TaskNode<Input = Input> + Clone + 'static>(
&mut self,
node_id: NodeId<T>,
)
pub fn starts_with<T: TaskNode<Input = Input> + Clone + 'static>( &mut self, node_id: NodeId<T>, )
Marks the node where execution should start.
§Examples
use swiftide_tasks::{NodeError, Task};
let mut task = Task::<i32, i32>::new();
let start = task.register_node_fn(|input: &i32| -> Result<i32, NodeError> { Ok(*input) });
task.starts_with(start);Sourcepub fn transitions_to_finish(
&self,
) -> impl Fn(Output) -> Transition + Send + Sync + 'static
pub fn transitions_to_finish( &self, ) -> impl Fn(Output) -> Transition + Send + Sync + 'static
Returns a typed transition closure that finishes the task with the final output.
Use this from the final node of a task. Fan-out branches cannot finish independently; when multiple branches are conceptually terminal, route them to a join node and finish from that join node instead.
§Examples
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) });
task.starts_with(start);
task.register_transition(start, task.transitions_to_finish())?;
assert_eq!(task.run(2).await?, TaskRunOutcome::Completed(3));Sourcepub async fn run(
&mut self,
input: impl Into<Input>,
) -> Result<TaskRunOutcome<Output>, TaskError>
pub async fn run( &mut self, input: impl Into<Input>, ) -> Result<TaskRunOutcome<Output>, TaskError>
Starts the task from its configured start node.
Returns TaskRunOutcome::Completed when the task reaches its finish transition, or
TaskRunOutcome::Paused when execution was intentionally paused.
§Errors
Returns an error when the task is already active, when the graph definition is incomplete, or when a node evaluation or transition fails while running the task.
Sourcepub fn reset(&mut self)
pub fn reset(&mut self)
Resets runtime state while keeping the graph definition and last start input.
After calling reset, use Task::resume to rerun the task from the start node with the
most recent input passed to Task::run.
Sourcepub async fn resume(&mut self) -> Result<TaskRunOutcome<Output>, TaskError>
pub async fn resume(&mut self) -> Result<TaskRunOutcome<Output>, TaskError>
Continues a paused or reset task.
§Errors
Returns an error when the task graph is invalid, when there is no paused or reset state to resume, or when a node evaluation or transition fails while continuing execution.
Sourcepub fn current_nodes<T: TaskNode + 'static>(&self) -> CurrentNodes<'_, T>
pub fn current_nodes<T: TaskNode + 'static>(&self) -> CurrentNodes<'_, T>
Returns the current paused or runnable nodes that have the requested type.
Paused branches take precedence over runnable branches. Runnable branches are only returned when no paused branches exist.
Sourcepub fn register_node<T>(&mut self, node: T) -> NodeId<T>
pub fn register_node<T>(&mut self, node: T) -> NodeId<T>
Registers a node in the task graph and returns its typed identifier.
§Examples
use async_trait::async_trait;
use swiftide_tasks::{DynNodeId, NodeError, Task, TaskNode};
#[derive(Clone)]
struct Increment;
#[async_trait]
impl TaskNode for Increment {
type Input = i32;
type Output = i32;
type Error = NodeError;
async fn evaluate(
&self,
_node_id: &DynNodeId<Self>,
input: &Self::Input,
) -> Result<Self::Output, Self::Error> {
Ok(*input + 1)
}
}
let mut task = Task::<i32, i32>::new();
let start = task.register_node(Increment);
let _ = start;Sourcepub fn register_node_fn<F, I, O, E>(
&mut self,
f: F,
) -> NodeId<SyncFn<F, I, O, E>>
pub fn register_node_fn<F, I, O, E>( &mut self, f: F, ) -> NodeId<SyncFn<F, I, O, E>>
Registers a synchronous closure as a task node.
This is the convenience entry point for examples, tests, and small bits of task glue.
For reusable domain logic, prefer implementing TaskNode directly and calling
Task::register_node.
§Examples
use swiftide_tasks::{NodeError, Task};
let mut task = Task::<i32, i32>::new();
let double = task.register_node_fn(|input: &i32| -> Result<i32, NodeError> {
Ok(*input * 2)
});
let _ = double;Sourcepub fn register_node_async_fn<F, I, O, E>(
&mut self,
f: F,
) -> NodeId<AsyncFn<F, I, O, E>>
pub fn register_node_async_fn<F, I, O, E>( &mut self, f: F, ) -> NodeId<AsyncFn<F, I, O, E>>
Registers an asynchronous closure as a task node.
§Examples
use swiftide_tasks::{NodeError, Task};
let mut task = Task::<i32, i32>::new();
let double = task.register_node_async_fn(|input: &i32| {
Box::pin(async move { Ok::<i32, NodeError>(*input * 2) })
});
let _ = double;Sourcepub fn register_transition<From, R>(
&mut self,
from: NodeId<From>,
transition: R,
) -> Result<(), TaskError>
pub fn register_transition<From, R>( &mut self, from: NodeId<From>, transition: R, ) -> Result<(), TaskError>
Registers how execution should continue after from completes.
The transition may be:
- a closure returning a typed
MarkedTransition - a closure returning a raw
Transitionfor advanced control flow - a
JoinTargetbuilt from a join node - a mapped join target produced by
JoinTarget::map
§Examples
use swiftide_tasks::{NodeError, Task};
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))?;§Errors
Returns an error when from is unknown, when the node already has a registered
transition, or when the transition type does not match the registered node type.
Sourcepub fn register_transition_async<From, R>(
&mut self,
from: NodeId<From>,
transition: R,
) -> Result<(), TaskError>
pub fn register_transition_async<From, R>( &mut self, from: NodeId<From>, transition: R, ) -> Result<(), TaskError>
Registers an asynchronous transition or async join payload mapping for from.
§Examples
use swiftide_tasks::{NodeError, Task};
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_async(start, move |value| async move { finish.transitions_with(value) })?;§Errors
Returns an error when from is unknown, when the node already has a registered
transition, or when the transition type does not match the registered node type.
Trait Implementations§
Auto Trait Implementations§
impl<Input, Output> !RefUnwindSafe for Task<Input, Output>
impl<Input, Output> !UnwindSafe for Task<Input, Output>
impl<Input, Output> Forget for Task<Input, Output>
impl<Input, Output> Freeze for Task<Input, Output>
impl<Input, Output> Send for Task<Input, Output>
impl<Input, Output> Sync for Task<Input, Output>
impl<Input, Output> Unpin for Task<Input, Output>
impl<Input, Output> UnsafeUnpin for Task<Input, Output>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more