pub struct DomainChain<D, T, S> { /* private fields */ }Expand description
A typed chain of sequential async command executions bound to a domain.
Created by DomainExecutor::exec or DomainExecutor::exec_discard.
Extend the chain with exec, then,
or exec_discard. Finish with go
to spawn the entire chain.
Generic over T — the output type of the last executed command — which
enables type-safe inter-command data passing via then.
§Execution model
All commands run sequentially: each completes fully before the next begins.
The chain is a single composed future — there is no parallelism within a chain.
If any command fails, the on_error callback is
invoked and remaining commands are skipped (short-circuit).
§Type parameters
D: The domain data type.T: The output type of the last command in the chain.S: The services type.
Implementations§
Source§impl<D, T, S> DomainChain<D, T, S>
impl<D, T, S> DomainChain<D, T, S>
Sourcepub fn exec<C>(
self,
cmd: C,
setter: impl Fn(&mut D, &C::Output) + Send + Sync + 'static,
) -> DomainChain<D, C::Output, S>
pub fn exec<C>( self, cmd: C, setter: impl Fn(&mut D, &C::Output) + Send + Sync + 'static, ) -> DomainChain<D, C::Output, S>
Execute a command independently, ignoring the previous output.
This command runs after the previous command completes. The previous
output is dropped — use then instead if you
need to pass data forward.
If the chain has already short-circuited (previous error), this command is skipped.
Sourcepub fn exec_discard<C>(self, cmd: C) -> DomainChain<D, (), S>
pub fn exec_discard<C>(self, cmd: C) -> DomainChain<D, (), S>
Execute a command and discard its output, ignoring the previous output.
This command runs after the previous command completes. The output is thrown away — no setter is needed.
Returns a chain with output type ().
Sourcepub fn then<C, F>(
self,
factory: F,
setter: impl Fn(&mut D, &C::Output) + Send + Sync + 'static,
) -> DomainChain<D, C::Output, S>
pub fn then<C, F>( self, factory: F, setter: impl Fn(&mut D, &C::Output) + Send + Sync + 'static, ) -> DomainChain<D, C::Output, S>
Execute a command whose input depends on the previous command’s output.
This command runs after the previous command completes. The factory
closure receives &T (the previous output) and returns the next command,
enabling multi-step pipelines where each step feeds the next:
use dbuff::*;
use std::time::Duration;
#[derive(Clone, Default)]
struct Data { total: i32 }
// Add(10) outputs 10, then Mul(3) receives 10 and outputs 30
domain.bind((), rt)
.exec(Add(10), |d, val: &i32| d.total = *val)
.then(|val: &i32| Mul(*val * 3), |d, val: &i32| d.total = *val)
.go();
tokio::time::sleep(Duration::from_millis(10)).await;
assert_eq!(domain.read().total, 30);If you don’t need the previous output, use exec instead.
If the chain has already short-circuited (previous error), the factory is not called and the chain remains short-circuited.
Sourcepub fn tracked(
self,
status_setter: impl Fn(&mut D, TaskStatus<T>) + Send + Sync + 'static,
) -> Self
pub fn tracked( self, status_setter: impl Fn(&mut D, TaskStatus<T>) + Send + Sync + 'static, ) -> Self
Add lifecycle status tracking to the last command in the chain.
Wraps the chain’s composed future with status transitions:
TaskStatus::Pendingbefore the chain segment runsTaskStatus::Resolvedwith the output value on successTaskStatus::Errorif the chain short-circuits (previous error)
The status_setter is called via SharedDomainData::modify at each
transition, writing the current TaskStatus into domain state. This
enables a render loop to poll status via domain.read():
use dbuff::*;
use std::time::Duration;
domain.bind((), rt)
.exec(Fetch(42), |_, _: &i32| {})
.tracked(|d, status: TaskStatus<i32>| d.status = status)
.go();
// Later, in a render loop:
// match &domain.read().status {
// TaskStatus::Pending => render_spinner(),
// TaskStatus::Resolved(v) => render_value(v),
// _ => {}
// }Multiple .tracked() calls can be chained to track different steps:
use dbuff::*;
use std::time::Duration;
domain.bind((), rt)
.exec(Step(1), |_, _: &i32| {})
.tracked(|d, status: TaskStatus<i32>| d.step1 = status)
.then(|v: &i32| Step(*v + 1), |_, _: &i32| {})
.tracked(|d, status: TaskStatus<i32>| d.step2 = status)
.go();Note: .tracked() tracks the entire chain segment up to that point,
including all previous commands. If a previous command in the chain
fails, the status will transition to TaskStatus::Error.
Sourcepub fn go(self) -> ChainHandle ⓘ
pub fn go(self) -> ChainHandle ⓘ
Spawn the entire chain as a single sequential task on the tokio runtime.
Commands execute one at a time — each completes before the next begins.
Returns a ChainHandle that resolves to
ControlFlow::Continue if all commands succeeded, or
ControlFlow::Break if any command failed (short-circuit).
Sourcepub fn go_detach(self)
pub fn go_detach(self)
Spawn the chain as a fire-and-forget task.
Identical to Self::go but returns () instead of a ChainHandle,
so no #[must_use] warning is emitted when the handle is not needed.