This is a classic parallel gateway design issue that requires comprehensive fixes across multiple areas. Let me break down the solution:
Parallel Gateway Configuration:
Your current gateway configuration is incomplete because it only defines success conditions. You need to explicitly handle both success and failure scenarios. Modify your parallel gateway to include rejection handling:
The gateway needs three distinct condition checks:
- Success: ALL paths approved → proceed to next activity
- Partial rejection: ANY path rejected → immediate termination and route to rejection handler
- Timeout: ANY path exceeds deadline → escalation
Your current XML only covers scenario 1. Add explicit rejection conditions:
<parallel_gateway id="DUAL_APPROVAL">
<success_condition>design.approved AND mfg.approved</success_condition>
<failure_condition>design.rejected OR mfg.rejected</failure_condition>
<failure_action>terminate_all_paths</failure_action>
</parallel_gateway>
The key is the failure_action directive that tells the workflow engine to immediately terminate all active parallel paths when the failure condition is met.
Join Condition Logic:
The join condition needs to be evaluated continuously, not just when paths complete. Implement a state-checking mechanism that monitors all parallel paths:
- Each approval activity must report its state change immediately to the parent gateway
- The gateway maintains a state table tracking each path’s current status
- On any state change, re-evaluate ALL join conditions (both success and failure)
- First condition to evaluate true takes precedence
This prevents the deadlock where the gateway is waiting for a success condition that can never be met because a failure has already occurred.
Rejection Propagation:
Implement proper rejection propagation that handles simultaneous rejections:
- When an approval activity transitions to rejected state, it must signal the parent gateway BEFORE completing
- The gateway receives the rejection signal and immediately flags all other parallel paths for termination
- Other parallel paths check for termination flag before processing their own state changes
- If termination flag is set, parallel paths abort their current operation and return control to gateway
- Gateway collects all path results and routes to the appropriate rejection handler
The critical piece is the termination flag check - this prevents the race condition where both paths try to propagate rejection simultaneously. The first rejection to reach the gateway wins, and the second rejection is absorbed as part of the coordinated termination.
Workflow Termination:
Ensure your workflow has proper cleanup when parallel paths terminate:
- Define a termination handler at the gateway level that cleans up any active assignments
- Release all locks held by parallel approval activities
- Clear any pending notifications or escalations
- Update workflow state to indicate which path triggered the rejection
- Log the termination event with details of all parallel path states at termination time
Without proper termination handling, you get orphaned workflow paths that keep the ECO in a “running” state even though no actual progress can occur.
Practical Fix for Your Scenario:
For your specific deadlock issue, the root cause is that your join condition only checks for approved status. When both paths reject, neither path meets the join condition, so the gateway waits indefinitely.
Implement this pattern:
- Add a workflow variable that tracks rejection count
- Each approval activity increments this counter on rejection
- Add a gateway condition that checks: if rejection_count > 0, route to rejection handler
- This condition should be evaluated BEFORE the success condition
- Add automatic path termination when the rejection condition triggers
This ensures that the first rejection (regardless of which path) immediately triggers the failure handling, and the second rejection is handled gracefully as part of the coordinated termination process.
Test this with simultaneous rejections to verify the deadlock is resolved and the workflow properly routes to your rejection handler activity.
This draft is based on general Aras Innovator knowledge. It has not been verified against your specific version and environment. Practitioners: verify the steps and share your experience below.