Execution Dependency Rules¶
This document describes how FlowDrop determines when a node is ready to execute based on its incoming edges (dependencies).
Overview¶
FlowDrop workflows consist of nodes connected by edges. Edges can be of different types:
| Edge Type | Purpose | Controls |
|---|---|---|
| Trigger | Controls execution flow | Whether a node executes at all |
| Data | Passes data between nodes | What input data a node receives |
The dependency rules determine: 1. When a node can execute (dependency satisfaction) 2. What data the node receives (data resolution)
Edge Types¶
Trigger Edges¶
Trigger edges connect to a node's trigger input port (typically named "trigger"). They control whether a node executes.
Handle format: {nodeId}-input-trigger
Examples: - Gateway branches (If/Else, A/B, Switch) - Sequential flow control - Event-driven execution
Data Edges¶
Data edges connect to a node's data input ports (any non-trigger port). They pass data from one node's output to another node's input.
Handle format: {nodeId}-input-{portName} (e.g., logger.1-input-message)
Loopback Edges¶
Loopback edges connect to a node's loopback input port (e.g., loop_back on ForEach nodes). They represent loop-back connections for iterative processing.
Handle format: {nodeId}-input-loop_back
Special behavior: - Excluded from dependency checking - they don't block node execution - Excluded from cycle detection - allows visual loops without breaking topological sort - Rendered with dotted lines in the workflow UI - Used primarily by iterator nodes (ForEach) to receive results from loop body
Dependency Rules¶
Rule 1: Trigger Edges Use OR Logic¶
When a node has trigger edges, it executes when at least ONE trigger source is satisfied.
┌─────────────┐
│ Gateway │
├─────────────┤
│ Branch A ───┼──trigger──┐
│ Branch B ───┼──trigger──┼──► [Node X]
└─────────────┘ │
│
[Other Node] ──trigger────┘
Node X executes when:
- Branch A is active, OR
- Branch B is active, OR
- Other Node completes
Rationale: Trigger edges typically come from branching logic where only one path is active at a time.
Rule 2: Data Edges to Different Ports Use AND Logic¶
When a node has data edges targeting different input ports, ALL ports must have at least one completed source.
[Source A] ──data──► port_x ─┐
├──► [Compare Node]
[Source B] ──data──► port_y ─┘
Compare Node executes when:
- Source A completes (provides port_x), AND
- Source B completes (provides port_y)
Rationale: If a node declares multiple distinct inputs, it likely needs all of them to function correctly.
Rule 3: Data Edges to Same Port Use OR Logic¶
When multiple data edges target the same input port, at least ONE source must complete.
[Template A] ──data──► message ─┐
├──► [Logger]
[Template B] ──data──► message ─┘
Logger executes when:
- Template A completes, OR
- Template B completes
Rationale: Multiple sources providing the same type of data (same port) typically represent alternative paths—only one value is needed.
Rule 4: Trigger Edges Take Priority¶
When a node has both trigger and data edges, only the trigger edges control execution timing. Data edges are used solely for data resolution.
[Gateway] ──trigger──────────────────► [Process Node]
↑
[Data Source] ──data──► input_data ─────────┘
Process Node executes when:
- Gateway trigger is satisfied
Data from Data Source is gathered IF it's available, but doesn't block execution.
Combined Rules Summary¶
| Scenario | Logic | Description |
|---|---|---|
| Multiple triggers | OR | Execute when ANY trigger is satisfied |
| Multiple data → same port | OR | Execute when ANY source for that port completes |
| Multiple data → different ports | AND | Execute when ALL ports have at least one source |
| Trigger + Data edges | Trigger controls | Data edges don't block; just gather available data |
| Loopback edges | Excluded | Never block execution; used for loop iteration |
Visual Examples¶
Example 1: Branching Workflow (Works Correctly)¶
┌──► [Template A] ──┐
[A/B Gateway] ──────┤ ├──► [Logger] (message port)
└──► [Template B] ──┘
- A/B Gateway activates either branch A or B
- Template A or Template B executes (not both)
- Logger has two data edges to the same
messageport - Logger executes when either Template completes (OR logic for same port)
Example 2: Parallel Inputs (Waits for All)¶
[User Input] ──► name ───┐
├──► [Greeting Generator]
[Time Service] ──► time ─┘
- Greeting Generator has two different ports:
nameandtime - Generator waits for BOTH sources (AND logic for different ports)
Example 3: Mixed Trigger and Data¶
[Button Click] ──trigger──────────────────► [Send Email]
↑
[Draft Email] ──data──► email_content ───────────┘
- Send Email has a trigger input and a data input
- Executes when: Button Click happens (trigger satisfied)
- Data: Gathers from Draft Email if available, but doesn't wait for it
Data Resolution¶
When a node executes, it receives data from completed upstream nodes:
Same Port Resolution (Multiple Sources)¶
When multiple sources target the same port and more than one has completed, the system uses the most recently completed source's value:
- Primary: Latest execution order (higher counter = more recent)
- Fallback: Alphabetical by node ID
A warning is logged when this occurs:
Multiple sources target the same input port 'message' on node 'logger.1'.
Previous source: 'template_a.1', current source: 'template_b.1'.
Using value from 'template_b.1' (resolved by latest execution order).
Missing Data¶
If a source node hasn't completed (e.g., branch not taken), its data is simply not included. The node executes with whatever data IS available.
Orchestrator-Specific Behavior¶
Pipeline-Based Orchestrators¶
SynchronousPipelineOrchestrator and queue-based execution use JobGenerationService::areJobDependenciesMet() to determine job readiness:
- Checks trigger satisfaction (OR logic)
- Checks data dependencies per-port (OR within port, AND across ports)
- Jobs are queued when ready
Direct Orchestrator¶
SynchronousOrchestrator uses pre-computed topological order:
- Nodes execute in dependency order
shouldExecuteNode()checks trigger conditions- Data is gathered from whatever executed parents are available
- Skipped nodes don't block downstream execution
Best Practices¶
DO: Use Same Port for Alternative Sources¶
[Option A] ──► input ─┐
├──► [Processor] ✅ Works with branching
[Option B] ──► input ─┘
DO: Use Different Ports for Required Parallel Data¶
[Source X] ──► port_a ─┐
├──► [Combiner] ✅ Waits for both
[Source Y] ──► port_b ─┘
DON'T: Connect Mutually Exclusive Sources to Different Ports¶
[Branch A] ──► port_a ─┐
├──► [Node] ❌ Will wait forever if Branch B taken
[Branch B] ──► port_b ─┘
Solution: Use same port or add trigger edges.
Related Documentation¶
- Internal Parameters - Special parameter handling
- Workflow Snapshots and Orchestrators - Orchestrator details
- Node Processor Development - Creating custom nodes