Overview
Conditional flow allows workflows to:- Branch execution based on runtime conditions
- Route data through different processing paths
- Skip nodes when conditions aren’t met
- Implement business logic with if/else and switch/case patterns
Use Cases
Validation
Check data validity and route to error handling or success paths
Routing
Direct data to different processors based on type or status
Error Handling
Implement fallback logic when operations fail
Business Rules
Encode complex decision trees and approval workflows
Architecture
CrystalFlow’s conditional flow is built on three key components:1. IConditionalNode Interface
Nodes implement this interface to enable branching:evaluateCondition() method:
- Is called after the node’s
execute()method runs - Returns the name of the output port representing the active branch
- Must return a valid output port name (e.g., ‘thenOutput’, ‘elseOutput’, ‘case_0’, ‘default’)
2. ConditionalStep
The execution engine builds conditional steps for branching nodes:3. Branch Execution
At runtime:- The conditional node executes (via
execute()method) evaluateCondition()is called to determine the active branch- Only the matching branch’s steps execute
- Other branches are completely skipped
Only the active branch executes - inactive branches are never run, making
conditional workflows efficient even with many branches.
Built-in Conditional Nodes
CrystalFlow includes two powerful conditional nodes out of the box.IfNode
TheIfNode provides classic if/else conditional logic:
condition = true→ Routes tothenOutput(then branch)condition = false→ Routes toelseOutput(else branch)- Optional
valueinput passes data through to active branch
- Validation
- Filtering
- Error Handling
SwitchNode
TheSwitchNode provides multi-way branching with case matching:
- Compares
valueagainst each case using strict equality (===) - Routes to matching
case_Xoutput - Falls back to
defaultoutput if no match - Optional
datainput passes through to active branch
cases property determines the number of outputs. When you add or remove cases, the node automatically updates its output ports.
- Status Routing
- Type Routing
- State Machine
Creating Custom Conditional Nodes
You can create custom conditional nodes for specialized branching logic:Example: GreaterThanNode
Example: MultiConditionNode
For complex branching with multiple conditions:Best Practices
Clear Output Names
Clear Output Names
Use descriptive output port names that clearly indicate what each branch represents.
Good: ‘thenOutput’, ‘elseOutput’, ‘validOutput’, ‘invalidOutput’
Bad: ‘out1’, ‘out2’, ‘output’
Error Handling
Error Handling
Validate inputs and throw meaningful errors:
Consistent Return Values
Consistent Return Values
Always return a valid output port name. The execution engine will error if
the returned value doesn’t match any output port.
Document Behavior
Document Behavior
Use JSDoc comments to explain what each branch represents and when it executes.
Branch Execution
Understanding how branches are built and executed is key to effective conditional workflows.Plan Building
During workflow validation, the execution engine:- Detects conditional nodes (nodes implementing IConditionalNode)
- For each output port of the conditional node:
- Finds all downstream nodes connected to that port
- Recursively builds execution steps for those nodes
- Creates a
ConditionalBranchwith those steps
- Stores all branches in a
ConditionalStep
Runtime Execution
When a conditional step executes:- Execute the node: The conditional node’s
execute()method runs - Evaluate condition:
evaluateCondition()is called to get the active branch - Find matching branch: The engine finds the branch with matching condition
- Execute branch steps: Only the matching branch’s steps execute recursively
- Skip other branches: All other branches are completely ignored
Events
The execution engine emits events for branch execution:Nested Conditionals
Conditional nodes can be nested inside branches for complex decision trees:If Inside If
Switch Inside If
Deep Nesting
CrystalFlow supports arbitrary nesting depth:Error Handling
Proper error handling ensures robust conditional workflows.Invalid Branch Name
IfevaluateCondition() returns a branch that doesn’t exist:
Error Propagation
Errors inside branches propagate normally:Validation Errors
Conditional nodes should validate their inputs:Always validate inputs in both
execute() and evaluateCondition() for
robust error handling.Testing Conditional Workflows
Effective testing ensures your conditional logic works correctly.Unit Testing Conditional Nodes
Integration Testing Workflows
Testing Nested Conditionals
Best Practices
Keep Conditions Simple
Keep Conditions Simple
Use dedicated logic nodes (CompareNode, IsPositiveNode) to compute boolean
conditions. Keep conditional nodes focused on routing, not complex logic.
Name Branches Clearly
Name Branches Clearly
Use descriptive output port names: ‘validOutput’/‘invalidOutput’ is better
than ‘output1’/‘output2’.
Handle All Cases
Handle All Cases
For SwitchNode, always handle the default case. Don’t assume value will
always match one of your cases.
Test All Branches
Test All Branches
Write tests that exercise each branch of your conditional logic to ensure
all paths work correctly.
Limit Nesting Depth
Limit Nesting Depth
Deeply nested conditionals are hard to maintain. Consider refactoring into
smaller workflows or using switch nodes for multi-way branching.
Use Events for Debugging
Use Events for Debugging
Listen to branch events during development to understand which paths execute
and debug unexpected behavior.
Examples
Conditional Logic Examples
See working examples with If and Switch nodes
Built-in Conditional Nodes
Complete API reference for IfNode and SwitchNode
Creating Custom Nodes
Learn to build your own conditional nodes
Execution Engine
Deep dive into execution plan architecture