Control Flow Patterns
Standard patterns for controlling workflow execution.
Basic Patterns
Sequence
Tasks execute one after another:
dart
builder
.start('begin')
.task('step1', ...)
.task('step2', ...)
.task('step3', ...)
.end('done')
.connect('begin', 'step1')
.connect('step1', 'step2')
.connect('step2', 'step3')
.connect('step3', 'done');Conditional Branching (Exclusive)
Route to exactly ONE path:
dart
builder
.start('begin')
.task('evaluate', ...)
.oneOf('decide', [
Branch.whenFn((o) => o['score'] >= 80, then: 'excellent'),
Branch.whenFn((o) => o['score'] >= 60, then: 'good'),
Branch.otherwise(then: 'needsWork'),
])
.task('excellent', ...)
.task('good', ...)
.task('needsWork', ...)
.end('done');Multi-Choice (Inclusive)
Route to ONE OR MORE paths:
dart
builder
.anyOf('notify', ['sendEmail', 'sendSms', 'sendPush']);Parallel Execution
Execute ALL paths concurrently:
dart
builder
.allOf('fork', ['taskA', 'taskB', 'taskC'])
.task('taskA', ...)
.task('taskB', ...)
.task('taskC', ...)
.allOf('join', ['afterJoin'])
.connect('taskA', 'join')
.connect('taskB', 'join')
.connect('taskC', 'join');Synchronization Patterns
Parallel Split + Synchronizing Merge
dart
// Fork to 3 parallel branches
builder.allOf('split', ['validateData', 'checkInventory', 'verifyPayment']);
// Each branch does its work
builder.task('validateData', ...);
builder.task('checkInventory', ...);
builder.task('verifyPayment', ...);
// Join waits for ALL branches
builder.allOf('synchronize', ['processOrder']);
// Edges from branches to join
builder.connect('validateData', 'synchronize');
builder.connect('checkInventory', 'synchronize');
builder.connect('verifyPayment', 'synchronize');Discriminator (First Wins)
Take the first branch to complete:
dart
// Simulate with inclusive gateway
builder.anyOf('race', ['useFast', 'useSlow']);Deferred Choice
Wait for one of multiple events:
dart
builder
.signalWait('waitForAction', signal: 'user_action', storeAs: 'action')
.oneOf('routeAction', [
Branch.whenFn((o) => o['action']?['type'] == 'approve', then: 'handleApprove'),
Branch.whenFn((o) => o['action']?['type'] == 'reject', then: 'handleReject'),
Branch.whenFn((o) => o['action']?['type'] == 'timeout', then: 'handleTimeout'),
]);Error Handling Patterns
Try-Catch
dart
builder
.task('riskyOperation', ...)
.oneOf('checkResult', [
Branch.whenFn((o) => o['success'] == true, then: 'continueNormal'),
Branch.whenFn((o) => o['error']?['retryable'] == true, then: 'retry'),
Branch.otherwise(then: 'handleError'),
]);Compensation
dart
// If step fails, run compensation
builder
.task('chargePayment', ...)
.task('fulfillOrder', ...)
.oneOf('checkFulfillment', [
Branch.whenFn((o) => o['fulfilled'] == true, then: 'complete'),
Branch.otherwise(then: 'compensate'),
])
.task('compensate', name: 'Refund Payment', ...)
.end('complete')
.end('compensated');Gateway Summary
| Pattern | Gateway | Behavior |
|---|---|---|
| Exclusive Choice | oneOf (XOR) | ONE path based on condition |
| Simple Merge | oneOf (XOR) | Merge exclusive paths |
| Multi-Choice | anyOf (OR) | ONE+ paths based on conditions |
| Parallel Split | allOf (AND) | ALL paths concurrently |
| Synchronization | allOf (AND) | Wait for ALL branches |
Next Steps
- Loop Patterns - Iteration
- Approval Workflows - Approval flows
- Best Practices - Design guidance