Control Flow
Processing Framework supports conditional control flow within a Procedure through a special system Operation called the Switcher. The Switcher evaluates condition expressions against Procedure and Execution parameters and determines which downstream Operations get executed.
This enables building Procedures that can take different processing paths depending on runtime values, without needing to create separate Procedures for each scenario.
How the Switcher Works
Section titled “How the Switcher Works”The Switcher Operation acts as a routing mechanism in a Procedure’s data flow. It evaluates one or more condition
expressions and, for each condition that evaluates to True, makes the corresponding output port available. Downstream
Operations connected to available output ports are executed as normal. Downstream Operations connected to unavailable
output ports are removed from the Procedure execution entirely, along with any further Operations that depend on
them.
Key behaviors:
- Zero or more output ports can become available, depending on how many conditions evaluate to
True. - Multiple conditions can be
Truesimultaneously, allowing parallel branches to execute. - If no conditions evaluate to
True, none of the Switcher’s downstream branches execute. - The Switcher itself does not produce data. It forwards data from upstream Operations through its output ports.
- Removal of branches is transitive: if a removed Operation’s output is consumed by another Operation, that Operation is also removed, and so on down the chain.
Switcher Structure
Section titled “Switcher Structure”A Switcher Operation is defined within a Procedure’s operations section. It uses the reserved identifier switcher
and has a structure similar to a regular Operation with some important additions.
{ "branch": { "identifier": "switcher", "version": 1, "name": "Switcher", "description": "Implements Procedure Logic flow control.",
"inputs": { "flow_control": { "sources": [ "upstream_op_a:output", "upstream_op_b:output" ] } },
"outputs": { "case_1": { "condition": "my_parameter == True", "sources": [ "upstream_op_a:output" ] }, "case_2": { "condition": "my_parameter == False", "sources": [ "upstream_op_b:output" ] }, "case_3": { "condition": "another_parameter == True" } } }}Inputs
Section titled “Inputs”The inputs section defines which upstream Operation outputs are available for the Switcher to forward. These act as
aliases, they make upstream data available as potential outputs of the Switcher. At least one input source is
required.
Outputs
Section titled “Outputs”Each entry in the outputs section defines a conditional output port (a “case”). Each case has:
| Field | Required | Description |
|---|---|---|
condition | Yes | A condition expression that is evaluated at execution time. |
sources | No | Which input port’s data to provide as the output for this case. If omitted, the port acts as a signal without forwarding data. |
data_type | No | The type of data output. Typically set to "*". |
If the condition evaluates to True, the output port becomes available and downstream Operations connected to it
will execute. If it evaluates to False, the port is absent and downstream Operations are removed.
Condition Expression Language
Section titled “Condition Expression Language”Condition expressions are strings that get evaluated at execution time. They support comparisons, logical operators, and references to Procedure parameters, Execution parameters, and Operation output parameters.
Comparison Operators
Section titled “Comparison Operators”| Operator | Description |
|---|---|
== | Equals |
!= | Not equal to |
< | Less than |
<= | Less than or equal to |
> | Greater than |
>= | Greater than or equal to |
Logical Operators
Section titled “Logical Operators”| Operator | Description |
|---|---|
and | Logical AND, both sides must be true |
or | Logical OR, at least one side must be true |
Reserved Words
Section titled “Reserved Words”| Word | Description |
|---|---|
True | Boolean true value |
False | Boolean false value |
Variables
Section titled “Variables”Variables are unquoted strings that reference parameter values. They must be resolvable at execution time or an error will be thrown.
- Procedure or Execution parameters: Use the parameter name directly (e.g.,
my_param). - Operation output parameters: Use the format
operation_name:parameter_name(e.g.,my_op:result).
A standalone variable name without any comparison operator is treated as NAME == True. For example, the condition
IS_ENABLED is equivalent to IS_ENABLED == True.
Literals
Section titled “Literals”- Strings: Must be quoted. Use single quotes to avoid escaping issues in JSON (e.g.,
'my_value'). - Numbers: Both integers and decimals are supported, including negative numbers. They must not be quoted (e.g.,
42,3.14,-10).
Parentheses
Section titled “Parentheses”Parentheses are fully supported for controlling evaluation priority.
"condition": "a == True or (b == False and c != 16)"
Limitations
Section titled “Limitations”- Parameter names and operation aliases that contain hyphens (
-) are not supported. Use underscores (_) instead. - Arithmetic operations (
+,-,*,/) are not supported in conditions. - List/array values cannot be compared directly.
Examples
Section titled “Examples”Example 1: Basic String Routing
Section titled “Example 1: Basic String Routing”Route processing to different branches based on a string parameter value. Only the branch whose condition matches
the BRANCH parameter will execute.
{ "operations": { "generate_file": { "identifier": "my_file_generator", "version": 1, "inputs": {}, "outputs": { "output": { "data_type": "*" } } },
"branch_switcher": { "identifier": "switcher", "version": 1, "inputs": { "flow_control": { "sources": ["generate_file:output"] } }, "outputs": { "case_1": { "condition": "BRANCH == 'foo'", "sources": ["generate_file:output"] }, "case_2": { "condition": "BRANCH == 'bar'", "sources": ["generate_file:output"] } } },
"foo_branch": { "identifier": "my_processor", "version": 1, "inputs": { "input": { "sources": ["branch_switcher:case_1"] } } },
"bar_branch": { "identifier": "my_processor", "version": 1, "inputs": { "input": { "sources": ["branch_switcher:case_2"] } } } },
"parameters": { "BRANCH": { "default_value": "foo", "description": "Controls which branch gets executed (foo or bar)" } }}Execution with default parameters (BRANCH = "foo"):
generate_fileexecutes.branch_switcherevaluates:case_1condition"foo" == 'foo'isTrue,case_2condition"foo" == 'bar'isFalse.foo_branchexecutes (receives data fromgenerate_file:output).bar_branchis removed, it is not executed.
Execution with BRANCH = "bar":
generate_fileexecutes.foo_branchis removed.bar_branchexecutes.
Example 2: Multiple Valid Branches
Section titled “Example 2: Multiple Valid Branches”When conditions are independent, multiple branches can execute simultaneously. Here, two separate parameters control two separate branches.
{ "outputs": { "case_1": { "condition": "BRANCH == 'foo'", "sources": ["generate_file:output"] }, "case_2": { "condition": "BRANCH2 == 'bar'", "sources": ["generate_file:output"] } }}Execution with BRANCH = "foo" and BRANCH2 = "bar":
- Both
case_1andcase_2evaluate toTrue. - Both downstream branches execute in parallel.
Example 3: No Valid Branches
Section titled “Example 3: No Valid Branches”If no conditions evaluate to True, all downstream branches connected to the Switcher are removed. The Procedure
still completes successfully, only Operations upstream of the Switcher and any Operations not connected to the
Switcher execute.
{ "outputs": { "case_1": { "condition": "BRANCH == 'foo'", "sources": ["generate_file:output"] }, "case_2": { "condition": "BRANCH2 == 'bar'", "sources": ["generate_file:output"] } }}Execution with BRANCH = "something_else" and BRANCH2 = "something_else":
- Neither condition matches.
generate_fileexecutes (it is upstream of the Switcher).foo_branchandbar_branchare both removed.- The Procedure finishes successfully with status
FINISHED.
Example 4: Boolean Logic and Operators
Section titled “Example 4: Boolean Logic and Operators”Conditions can use logical operators (and, or, !=) and parentheses. In this example, all four conditions
evaluate to True when BOOL_TRUE = true and BOOL_FALSE = false.
{ "outputs": { "and_case": { "condition": "BOOL_TRUE and BOOL_TRUE", "sources": ["generate_file:output"] }, "neq_case": { "condition": "BOOL_TRUE != BOOL_FALSE", "sources": ["generate_file:output"] }, "or_case": { "condition": "BOOL_TRUE or BOOL_FALSE", "sources": ["generate_file:output"] }, "parentheses_case": { "condition": "(BOOL_TRUE or BOOL_FALSE) and BOOL_TRUE", "sources": ["generate_file:output"] } }}| Case | Condition | Evaluates To |
|---|---|---|
and_case | true and true | True |
neq_case | true != false | True |
or_case | true or false | True |
parentheses_case | (true or false) and true | True |
Example 5: Numeric Comparisons
Section titled “Example 5: Numeric Comparisons”Conditions support numeric comparisons using <, <=, >, >=. In this example, all four conditions evaluate to
True when FLOAT = 42.1 and INT = 42.
{ "outputs": { "gt_case": { "condition": "FLOAT > INT", "sources": ["generate_file:output"] }, "gte_case": { "condition": "FLOAT >= FLOAT", "sources": ["generate_file:output"] }, "lt_case": { "condition": "INT < FLOAT", "sources": ["generate_file:output"] }, "lte_case": { "condition": "INT <= INT", "sources": ["generate_file:output"] } }}| Case | Condition | With FLOAT=42.1, INT=42 | Evaluates To |
|---|---|---|---|
gt_case | FLOAT > INT | 42.1 > 42 | True |
gte_case | FLOAT >= FLOAT | 42.1 >= 42.1 | True |
lt_case | INT < FLOAT | 42 < 42.1 | True |
lte_case | INT <= INT | 42 <= 42 | True |
Example 6: Combining Multiple Condition Types
Section titled “Example 6: Combining Multiple Condition Types”Conditions can combine comparisons with logical operators and parentheses for more complex routing logic.
"condition": "ex_parameter >= 10 and proc_parameter == 'single'""condition": "a == True or (b == False and c != 16)"Example 7: Simplest Conditions
Section titled “Example 7: Simplest Conditions”The simplest possible conditions use the boolean literals directly:
"condition": "True""condition": "False"A condition of "True" means the output port is always available. A condition of "False" means it is never
available. These can be useful during development or testing.
Chaining Switchers
Section titled “Chaining Switchers”Multiple Switcher Operations can be chained together within a single Procedure. The output of one Switcher can feed into a downstream Switcher, enabling multi-level conditional logic.
For example, a first Switcher might route based on a high-level parameter, and a second Switcher within one of those branches might further subdivide the flow based on a more specific parameter.
When chaining Switchers, the transitive removal behavior still applies: if a parent Switcher’s condition evaluates
to False, all downstream Operations, including any chained Switchers and their branches, are removed.