Skip to main content
These ten processors are always part of the server. They route messages by port, split and batch them, pace them, repeat other plugins, run other workflows and wait for people. Routing works by port name: a message leaves a node on one port, and the engine delivers it only along edges whose sourcePort names that port. An edge with no sourcePort receives every message of the node. See Nodes, edges and ports and Routing and branching. Options marked “expression” take the expression language described in Variables and expressions. Inside an expression the message is the root, so payload.status reads a payload field and metadata.key reads a metadata entry. These plugins do not resolve ${...} variables in their options. Unless a section says otherwise, the default timeout is the engine default of 30 seconds idle (see Time limits).

BRANCH

Sends each message to one port, or several, chosen by an exact match or by conditions. Output ports: every port named in cases, plus defaultPort and errorPort when set. Each port named in cases or defaultPort must have an outgoing edge, or the workflow is rejected at validation. In SELECT_KEY mode the selector result is compared as text, so a number 3 matches the case key "3". In EXPRESSION mode cases are tried in the order written. With strictMode on, a message that matches nothing and has no defaultPort is an error, so a typo in a case cannot silently lose data. With strictMode off such a message is dropped. This node routes a quality gate on two payload fields:

FILTER

Keeps messages that match a condition. A message that does not match is dropped, or sent to a second port. Output ports: default, plus discardPort when set. The SIMPLE engine accepts one test of the form path operator value, where the path starts with payload. or metadata.: The engine value REGO is not supported and is rejected at validation.

SPLITTER

Splits one message that holds a list into one message per item. Output ports: default, plus errorPort when set. Each item message has a new id and the item as its payload. It keeps the parent’s metadata, trace id and priority, and carries the position of the item in the batch (sequenceNumber from 1, and sequenceSize) with the parent’s id as its correlation id. Items of one parent are emitted in order.

AGGREGATE

Batches messages into one message that holds a list. It is the reverse of SPLITTER. Output port: default. The batch message has a new id, the trace id of its first message, and the payload {"items": [...], "count": n}, where items holds the payloads in arrival order. Batching is by arrival only: messages are not grouped by correlation id. A partial batch is always sent when the input ends. Without timeoutMs, a partial batch waits in memory until it fills or the input ends.

RECIPIENT_LIST

Copies one message to several ports at once. Output ports: in STATIC mode the names in recipients plus errorPort. In the other modes the plugin can emit on any port name, so the engine accepts whatever the expression returns. A result that is empty or null sends nothing. Each recipient receives its own copy of the message on the port of that name.

DELAY

Holds each message for a fixed time and releases them one at a time, in order. Output port: default. Ten messages with delayMs 100 take about a second, which makes DELAY a simple way to stay under an outside rate limit. Because the node’s idle timeout is 30 seconds, set timeoutSeconds on the node when delayMs is close to or above 30000.

LOOP_PREDICATE and LOOP_STREAM

Run another processor again and again on a message. This is how Yukta polls and retries until a condition holds without breaking the rule that a workflow has no cycles. LOOP_PREDICATE emits only the final result. LOOP_STREAM emits every message that every iteration produced. Output port: default. Each iteration runs the target on the current message. The target’s result becomes the input of the next iteration. The loop ends when exitCondition is true, when maxIterations is reached or when maxDuration has passed; reaching a limit is not an error. For LOOP_PREDICATE, an iteration uses the last message the target emitted. targetConfig is not checked when the workflow is validated, so a mistake in it appears only at run time. The target must be an installed processor. These nodes emit nothing until the loop ends, so set timeoutSeconds on the node to at least maxDuration when a loop can run longer than 30 seconds. This node checks a command up to five times, one second apart, and stops after the third check:
See Loops and retries for choosing between a loop and the engine’s own retry.

SUB_WORKFLOW

Runs another workflow of the same session for each message and emits what that workflow produced. Output port: default. Messages are handled one at a time. The output payload is {"executionId": "...", "results": [...]}: the child’s own execution id and the payload of every message that reached a terminal node of the child, in order. The node fails when the workflow does not exist, the child fails, or timeoutSeconds passes. The child is a normal execution with its own id. It is tracked and controllable like any other. It does not take an execution slot of its own: it uses the slot its parent holds, so it does not count towards the admission limits. The child’s start payload also carries yukta.depth and yukta.parentExecutionId. Workflows can nest at most 5 levels deep, which stops a workflow from starting itself forever. Default timeout: timeoutSeconds plus 10 seconds, so 310 seconds with the default.
See Sub-workflows.

WAIT_FOR_SIGNAL

Holds each message until a named signal arrives. Use it for approvals and for waiting on a person or another system. Output port: default. Messages are held one at a time, in order. When a signal arrives the plugin releases the message with three metadata entries added: signal.name, signal.decision and signal.data. Read them in a later node, for example with metadata['signal.decision'] in a BRANCH expression. A decision of reject (any capitalisation) is a rejection. Any other decision, such as approve, releases the message. Send the signal to the waiting node of a running execution:
The request answers 409 when the node is not waiting for that name. List the nodes that wait now with GET /api/sessions/{sessionId}/approvals. Signal behaviour:
  • A signal that arrives before its wait is kept for 10 minutes, at most 100 at a time, and is taken by the wait that follows.
  • A second signal for the same node and name within 5 seconds of an accepted one counts as a double submit and is answered as not waiting.
  • The answer is recorded with the node’s checkpoint, so a resumed execution reuses it for the same message instead of waiting again.
  • Waits are held in memory. After a server restart, an execution that is resumed waits for a new signal.
Default timeout: timeoutSeconds plus 30 seconds, so 3630 seconds with the default.
See Approvals and signals.

Limits and defaults