跳到主要内容

Waits

查看 Markdown

WaitFor returns a Wait: a wait type and the conditions to wait for. Dex stores the wait durably and checks the conditions whenever related state changes. A condition waits for a Timer, a Channel, or a SubFlow.

  • Until waits for one condition.
  • AnyOf is met when any condition is met.
  • AllOf is met when all conditions are met.
  • AnyCombinationOf is met when any one group of conditions is all met.

Until, AnyOf, and AllOf do not need condition IDs. Read Channel results from the Channel definition, and check Timer outcomes through the Context. Add a condition ID only where an API requires one, such as AnyCombinationOf or a Timer that you select by ID.

TypeScript
return Wait.anyOf(
channelA.forOne(),
Timer.byDuration(timeoutMs),
);

Example: examples/typescript/src/primitives/wait-types/wait-types-flow.ts

TypeScript
return Wait.allOf(
channelA.forOne(),
channelB.forOne(),
);

Example: examples/typescript/src/primitives/wait-types/wait-types-flow.ts

To pass a value from WaitFor to Execute, see Step execution local.

Condition results​

After WaitFor completes, Execute can read what satisfied the Wait. For a Channel, call results on the Channel to read the messages the wait consumed. For a SubFlow, call SubFlow.getConditionResults to read the child Flow result.

In an AnyOf, Dex consumes messages only from the Channel condition that it selects to satisfy the Wait. Other Channel conditions consume nothing, even if they are also ready, and their messages stay queued.

When several AnyOf conditions are ready at the same check, Dex selects the first ready one in this order: Timer conditions, then Channel conditions, then SubFlow conditions, each kind in the order you declared them. A condition that is not ready does not block a later one that is. So across kinds, the order of the arguments in your call does not decide which condition wins.

Use AnyOf when any ready condition may win. If the Step must keep waiting for a higher-priority input, return only that condition until it resolves.

Channel results​

TypeScript
const approval = new Channel("Approval", stringCodec);

class ChannelWait implements Step<number> {
public readonly inputCodec = doubleCodec;

public getStepType(): string {
return "ChannelWait";
}

public waitFor(_context: Context, input: number): Wait {
return Wait.anyOf(
approval.forOne(),
Timer.byDuration(input * 1000),
);
}

public execute(context: Context, _input: number): StepDecision {
if (context.hasTimerFired()) {
return gracefulComplete("approval timed out");
}
const approvals = approval.results(context);
return gracefulComplete(approvals[0]!);
}
}

const channelWait = new ChannelWait();

Example: examples/typescript/src/primitives/channel/channel-flow.ts

SubFlow results​

TypeScript
public execute(context: Context, _input: number): StepDecision {
const result = SubFlow.getConditionResults(context);
const output = result.singleOutput(doubleCodec);
const flowId = SubFlow.getFlowId(context);
return gracefulComplete(`${flowId}|${output}`);
}

Example: examples/typescript/src/primitives/subflow/subflow-flow.ts

Join parallel branches​

Since 1.44.0. A Join waits for the parallel branches that one Step started. It stores branch results in a ChannelMap with the Join's name, so its conditions are Channel conditions. They combine with AnyOf, AllOf, and Timers.

  • new Join defines a Join. Add it to channels of PersistenceSchema, like a ChannelMap. Decode a JoinRound Step input with joinRoundCodec.
  • Join.fork starts one round from a split Step. It returns the branch movements and the join Step movement. Join.forkWithRoundKey does the same with an explicit round key, for example in an RPC.
  • A branch reports its result with Join.endBranch or Join.reportBranchResult.
  • The join Step waits with Join.forAllBranches, Join.forFirstBranch, or Join.forBranches, and reads Join.branchResults.
  • The next round's split Step resets the previous round with Join.forRemainingBranches, and reads Join.remainingBranchResults.
  • Join.channelMap returns the underlying ChannelMap, for reading a round's pending results. Never publish to it directly.

The Join API reference documents each method. The Await Parallel Steps pattern shows the whole shape.

Example: examples/typescript/src/patterns/parallel/parallel-step-flows.ts

AnyCombinationOf​

AnyCombinationOf is met when every condition in any one group is met. Each group is an all-of combination.

Dex consumes messages only from the Channel conditions of the group it selects. Conditions that belong only to other ready groups consume nothing, and their messages stay queued.

Every condition in the groups needs a unique condition ID.

TypeScript
return Wait.anyCombinationOf(
ConditionCombination.of(
channelA.forOne("signal-a"),
Timer.byDuration(timeoutMs, "timeout"),
),
ConditionCombination.of(channelB.forOne("signal-b")),
);

Example: examples/typescript/src/primitives/wait-types/wait-types-flow.ts

Skip immediately​

SkipWaitImmediately waits for no condition. Use it when WaitFor decides at run time that the Step should not wait.

TypeScript
return Wait.skipImmediately();

Example: examples/typescript/src/primitives/flow/example-flow.ts