Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reject duplicate parallel gateway activate command #9759

Merged
merged 5 commits into from
Jul 15, 2022

Conversation

remcowesterhoud
Copy link
Contributor

@remcowesterhoud remcowesterhoud commented Jul 12, 2022

Description

Parallel gateways get activated by taking a sequence flow and checking if the number of taken flows is greater or equal to the number of incoming sequence flows. If this is the case an activate command is sent. The number of taken sequence flows get rest upon activation of the parallel gateway.

This proves troublesome when a "bad" model causes one of the incoming sequence flows to be taken twice. This could result in the activation command being sent twice. Imagine there is a parallel gateway with 2 incoming flows. What would happen is:

  1. First flow is taken
  2. Second flow is taken. Incoming flows == taken flows so an activate command is sent.
  3. Second flow is taken again. The first activate command has not been processed yet. The number of taken flows has not been reset. As a result incoming flows < taken flows. A second activate command is sent.

This is solved by always sending an activate command when a sequence flow is taken. Once the BpmnStreamProcessor tries to process the record it will check if the state is valid. Here a check has been added to verify that when we receive an activate command for a parallel gateway we will first check if all the incoming flows have been taken. If this is not the case we will reject the command.

Related issues

closes #6778

Definition of Done

Not all items need to be done depending on the issue and the pull request.

Code changes:

  • The changes are backwards compatibility with previous versions
  • If it fixes a bug then PRs are created to backport the fix to the last two minor versions. You can trigger a backport by assigning labels (e.g. backport stable/1.3) to the PR, in case that fails you need to create backports manually.

Testing:

  • There are unit/integration tests that verify all acceptance criterias of the issue
  • New tests are written to ensure backwards compatibility with further versions
  • The behavior is tested manually
  • The change has been verified by a QA run
  • The impact of the changes is verified by a benchmark

Documentation:

  • The documentation is updated (e.g. BPMN reference, configuration, examples, get-started guides, etc.)
  • New content is added to the release announcement
  • If the PR changes how BPMN processes are validated (e.g. support new BPMN element) then the Camunda modeling team should be informed to adjust the BPMN linting.

Please refer to our review guidelines.

Parallel gateways get activated by taking a sequence flow and checking if the number of taken flows is greater or equal to the number of incoming sequence flows. If this is the case an activate command is sent. The number of taken sequence flows get rest upon activation of the parallel gateway.

This proves troublesome when a "bad" model causes one of the incoming sequence flows to be taken twice. This could result in the activation command being sent twice. Imagine there is a parallel gateway with 2 incoming flows. What would happen is:

1. First flow is taken
2. Second flow is taken. Incoming flows == taken flows so an activate command is sent.
3. Second flow is taken again. The first activate command has not been processed yet. The number of taken flows has not been reset. As a result incoming flows < taken flows. A second activate command is sent.
@github-actions
Copy link
Contributor

github-actions bot commented Jul 12, 2022

Unit Test Results

   792 files  ±    0     792 suites  ±0   1h 42m 3s ⏱️ + 1m 24s
6 219 tests +219  6 211 ✔️ +219  8 💤 ±0  0 ±0 
6 388 runs  +219  6 380 ✔️ +219  8 💤 ±0  0 ±0 

Results for commit aa9fab1. ± Comparison against base commit 275a7d2.

♻️ This comment has been updated with latest results.

@remcowesterhoud remcowesterhoud removed the request for review from korthout July 12, 2022 09:13
@remcowesterhoud
Copy link
Contributor Author

@korthout I have removed you as a reviewer for now, since the solution is flawed. Sorry!

@korthout
Copy link
Member

@remcowesterhoud I like the idea of rejecting the activate command for the parallel gateway when it isn't yet ready to activate. It would allow us to remove the logic that determines whether or not to write the activate command, and entirely move it to the processor.

This also makes it more in line with other concurrent behaviors (e.g. an element might be planned to be completed because a COMPLETE_ELEMENT was written for it on the log, but before it is processed a TERMINATE_ELEMENT is processed due to some interruption like a boundary event, we then reject the COMPLETE_ELEMENT command when we try to process it later).

To make this idea work for Start Process Instance Anywhere, we need something special. We'll need to increment the number of taken sequence flows before processing the ACTIVATE_ELEMENT of the parallel gateway:

  • for each parallel gateway that is targetted by a start instruction,
  • for each incoming sequence flow,
  • within the related flow scope instance.

We could do that by introducing a new event applier for ProcessInstanceCreation CREATED events, which is written (and applied) before the ACTIVATE_ELEMENT of the parallel gateway is processed.

The hard part is to find the related flow scope instance, because you don't have access to the key of the parallel gateway's element instance (i.e. the parallel gateway isn't created yet). There is no direct access to this, but you could traverse the process instance's process model using ElementInstanceState.getChildren(key).

@remcowesterhoud If you want we can talk about it in person.

…cess anywhere

In the scenario where we start a process instance at a Parallel Gateway we will have to increment the number of taken sequence flows manually. If we don't do this the new state transition guard will find no taken sequence flows, where it has N amount of incoming flows. Resulting in a command rejection.
By incrementing the number of taken sequence flows for each incoming flow of the parallel gateway we can circumvent this rejection and activate the gateway as expected.
This check has been moved to the ProcessInstanceStateTransitionGuard. We can always send the activate command. If a parallel gateway cannot be activated the command gets rejected.
This might have a small impact on performance, as now we are sending commands and rejecting them, as opposed to not sending the commands at all.
@remcowesterhoud
Copy link
Contributor Author

@korthout Thanks for your help ❤️

I have resolved the issues, please have a look!

Copy link
Member

@korthout korthout left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Nice work @remcowesterhoud

🔧 Please make it clear in the PR description what this PR changes.
🔧 Please document the new Parallel Gateway behavior.

💭 This will probably not backport so easily to the older versions, because of the new event applier (those versions don't know about start instructions).

👍 LGTM

@remcowesterhoud
Copy link
Contributor Author

bors merge

zeebe-bors-camunda bot added a commit that referenced this pull request Jul 15, 2022
9759: Reject duplicate parallel gateway activate command r=remcowesterhoud a=remcowesterhoud

## Description

<!-- Please explain the changes you made here. -->
Parallel gateways get activated by taking a sequence flow and checking if the number of taken flows is greater or equal to the number of incoming sequence flows. If this is the case an activate command is sent. The number of taken sequence flows get rest upon activation of the parallel gateway.

This proves troublesome when a "bad" model causes one of the incoming sequence flows to be taken twice. This could result in the activation command being sent twice. Imagine there is a parallel gateway with 2 incoming flows. What would happen is:

1. First flow is taken
2. Second flow is taken. Incoming flows == taken flows so an activate command is sent.
3. Second flow is taken again. The first activate command has not been processed yet. The number of taken flows has not been reset. As a result incoming flows < taken flows. A second activate command is sent.

This is solved by always sending an activate command when a sequence flow is taken. Once the `BpmnStreamProcessor` tries to process the record it will check if the state is valid. Here a check has been added to verify that when we receive an activate command for a parallel gateway we will first check if all the incoming flows have been taken. If this is not the case we will reject the command.

## Related issues

<!-- Which issues are closed by this PR or are related -->

closes #6778 



Co-authored-by: Remco Westerhoud <remco@westerhoud.nl>
@zeebe-bors-camunda
Copy link
Contributor

Build failed:

Expand the test to also assert that we reject the command twice, and only activate it once.
@remcowesterhoud remcowesterhoud force-pushed the 6778_negate_active_sequence_flow_count branch from 327fd61 to aa9fab1 Compare July 15, 2022 14:47
@remcowesterhoud
Copy link
Contributor Author

bors retry

@zeebe-bors-camunda
Copy link
Contributor

Build succeeded:

@zeebe-bors-camunda zeebe-bors-camunda bot merged commit 2c5304e into main Jul 15, 2022
@zeebe-bors-camunda zeebe-bors-camunda bot deleted the 6778_negate_active_sequence_flow_count branch July 15, 2022 15:12
@backport-action
Copy link
Collaborator

Successfully created backport PR #9822 for stable/1.3.

@backport-action
Copy link
Collaborator

Successfully created backport PR #9823 for stable/8.0.

@skayliu skayliu mentioned this pull request Jul 16, 2022
10 tasks
@korthout korthout mentioned this pull request Jul 19, 2022
10 tasks
zeebe-bors-camunda bot added a commit that referenced this pull request Jul 20, 2022
9822: [Backport stable/1.3] Reject duplicate parallel gateway activate command r=remcowesterhoud a=backport-action

# Description
Backport of #9759 to `stable/1.3`.

relates to #6778

Co-authored-by: Remco Westerhoud <remco@westerhoud.nl>
zeebe-bors-camunda bot added a commit that referenced this pull request Jul 20, 2022
9823: [Backport stable/8.0] Reject duplicate parallel gateway activate command r=remcowesterhoud a=backport-action

# Description
Backport of #9759 to `stable/8.0`.

relates to #6778

Co-authored-by: Remco Westerhoud <remco@westerhoud.nl>
zeebe-bors-camunda bot added a commit that referenced this pull request Jul 20, 2022
9822: [Backport stable/1.3] Reject duplicate parallel gateway activate command r=remcowesterhoud a=backport-action

# Description
Backport of #9759 to `stable/1.3`.

relates to #6778

Co-authored-by: Remco Westerhoud <remco@westerhoud.nl>
zeebe-bors-camunda bot added a commit that referenced this pull request Jul 20, 2022
9823: [Backport stable/8.0] Reject duplicate parallel gateway activate command r=remcowesterhoud a=backport-action

# Description
Backport of #9759 to `stable/8.0`.

relates to #6778

Co-authored-by: Remco Westerhoud <remco@westerhoud.nl>
zeebe-bors-camunda bot added a commit that referenced this pull request Jul 20, 2022
9823: [Backport stable/8.0] Reject duplicate parallel gateway activate command r=remcowesterhoud a=backport-action

# Description
Backport of #9759 to `stable/8.0`.

relates to #6778

Co-authored-by: Remco Westerhoud <remco@westerhoud.nl>
zeebe-bors-camunda bot added a commit that referenced this pull request Jul 20, 2022
9823: [Backport stable/8.0] Reject duplicate parallel gateway activate command r=remcowesterhoud a=backport-action

# Description
Backport of #9759 to `stable/8.0`.

relates to #6778

Co-authored-by: Remco Westerhoud <remco@westerhoud.nl>
zeebe-bors-camunda bot added a commit that referenced this pull request Jul 21, 2022
9825: Joining parallel gateway doc r=remcowesterhoud a=remcowesterhoud

## Description

<!-- Please explain the changes you made here. -->
Add a bpmn diagram explaining the activation of a joining parallel gateway

## Related issues

<!-- Which issues are closed by this PR or are related -->

relates to #9759 



Co-authored-by: Remco Westerhoud <remco@westerhoud.nl>
@korthout
Copy link
Member

korthout commented Aug 2, 2022

@remcowesterhoud Please add this to the release notes

@Zelldon Zelldon added the version:8.1.0 Marks an issue as being completely or in parts released in 8.1.0 label Oct 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
version:1.3.13 version:8.1.0-alpha4 version:8.1.0 Marks an issue as being completely or in parts released in 8.1.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

IllegalStateException: Not expected to have an active sequence flow count lower then zero!
5 participants