Skip to content

Choice

The Choice processor implements the Content-Based Router EIP — an if/elseif/else over message content. Each when clause pairs a predicate with a branch; the first predicate that matches wins, and only its branch runs. An optional otherwise branch runs when no predicate matched.

Processors in this file

NewChoice

YAML form:

steps:
  - choice:
      when:
        - starlang: body().type == "order"
          steps:
            - target: kafka://orders
        - starlang: body().type == "refund"
          steps:
            - target: kafka://refunds
      otherwise:
        steps:
          - log: { message: "unrouted message", level: "WARN" }
          - target: kafka://dead-letter
Field Type Default Description
when list of when-clauses required Predicate + branch pairs. Evaluated top-to-bottom; the first match is taken.
when[].starlang string required Starlang predicate.
when[].steps list required Branch to run when the predicate matches.
when[].target string optional Shorthand for a single target: step.
otherwise.steps list optional Fallback branch when no when matched.
otherwise.target string optional Shorthand for a single target: step.

Constructor: NewChoice() *Choice, then .When(pred, proc) and .SetOtherwise(proc) builders.

How it works:

  1. Iterates Whens in order.
  2. For each, calls Predicate.Matches(ctx, ex). The first true wins — the associated Processor runs and Choice returns.
  3. If no predicate matched and Otherwise is set, runs it.
  4. If no predicate matched and Otherwise is nil, returns nil (no-op).

Pitfalls:

  • Choice is first-match wins. To execute every matching branch, use MessageRouter with AllMatch: true.
  • Predicate evaluation errors are returned immediately — they do not fall through to otherwise.
  • Predicates are evaluated lazily (Choice short-circuits), so put cheap/likely cases first.

Examples

workflows:
  - id: triage
    trigger: { uri: http://localhost:8080/events }
    steps:
      - choice:
          when:
            - starlang: header("X-Priority") == "high"
              steps:
                - target: kafka://high-priority
            - starlang: header("X-Priority") == "low"
              steps:
                - target: kafka://low-priority
          otherwise:
            target: kafka://default

Source

pkg/processor/choice.go

See also

  • filter — single-predicate gating.
  • normalize — Choice-shaped, but semantically aimed at format normalization (Message Normalizer EIP).
  • eip_advanced — MessageRouter for the data-driven, all-match variant.
  • routing — RecipientList, RoutingSlip, DynamicRouter for endpoint-driven routing.