跳到主要内容

Step decisions

查看 Markdown

Execute returns a StepDecision. The decision moves to next Steps, closes the Flow, or stops this branch. It can also cancel other Steps.

Multiple next Steps​

GoTo starts one next Step. GoToMany starts multiple next Steps. Each Step movement has its own input and can also have its own Step options.

Rust
Ok(StepDecision::go_to_many([
StepMovement::to(&CarrierA, quote_a),
StepMovement::to(&CarrierB, quote_b),
StepMovement::to(&Winner, winner_quote),
]))

Example: examples/rust/src/primitives/step_decision/flow.rs

Close decisions​

DecisionWhat it does
GracefulCompleteStops this branch and marks the Flow to complete. The Flow completes when every branch and Step has stopped.
DeadEndStops this branch only.
ForceCompleteCompletes the Flow immediately.
ForceFailFails the Flow immediately.

GracefulComplete and ForceComplete can carry an output. ForceFail carries a failure reason. The Flow result lists each output with its Step type and Step execution ID. When several Steps complete gracefully, the result contains all their outputs.

DeadEnd stops this branch without marking the Flow to complete. A Flow with no active Steps can keep running.

Rust
"graceful" => Ok(StepDecision::graceful_complete(String::from("done"))),
"dead-end" => Ok(StepDecision::go_to_many([
StepMovement::to(&BranchWorker, "left".to_string()),
StepMovement::to(&BranchWorker, "right".to_string()),
])),

Ok(StepDecision::dead_end())

Example: examples/rust/src/primitives/step_decision/flow.rs

Rust
fn execute(&self, _context: &mut Context, _input: ()) -> HandlerResult<StepDecision> {
Ok(StepDecision::force_fail("task exceeded graceful timeout"))
}

fn execute(&self, _context: &mut Context, _successful: bool) -> HandlerResult<StepDecision> {
Ok(StepDecision::force_complete("task-completed".to_string()))
}

Example: examples/rust/src/patterns/timeout/flow.rs

Cancel other Steps​

A StepDecision can cancel other active Steps.

  • CancelSteps selects active Steps by Step type.
  • CancelSiblingSteps selects active Steps that were triggered by the same parent Step execution.

An RPC can also cancel Steps by type. See Cancel running Steps. For how a running attempt observes cancellation, see Cancellation.

When Dex cancels a Step before its Execute commits, it returns the Channel messages that the Step's wait consumed. They go back to the front of their Channels, in their original order. A Step that the decision cancels also never receives the messages that the same decision publishes. Neither applies when the decision also closes the Flow with ForceComplete or ForceFail. See Canceled Steps return consumed messages.

Rust
Ok(StepDecision::go_to(&RecordQuote, quote)
.cancel_step(&CarrierA)
.cancel_step(&CarrierB))

Example: examples/rust/src/primitives/step_decision/flow.rs

ForceCompleteIfChannelsEmpty​

ForceCompleteIfChannelsEmpty checks all named Channels in one atomic step. If every one is empty, it completes the Flow. Otherwise, it goes to the given next Steps. A Channel with queued messages is non-empty. A Channel also stays non-empty after a Step consumes a message from it, until that Step's Execute finishes. A message that a canceled Step returned is pending again, so its Channel is non-empty too.

Use it to complete a Flow once its Channels are drained, so the Flow stays short. See Drain External Channel for the full example.

Rust
Ok(StepDecision::force_complete_if_channels_empty(
(),
StepMovement::to(&DrainChannel, ()),
[channel_queue().when_empty()],
))

Example: examples/rust/src/patterns/drain_channels/flow.rs