some person review the task and make their choice, and the next task is just based on whether all of them approve the task or not. Let’s say, if a person approve his task, the approvedCount variable will be plused one(approvedCount = approvedCount + 1).
The problem is that the user task is parallel multi instance which means two or more person may complete their use task at the same time. If it happens, the variable approvedCount in on race condition and its value is unpredictable.
May I know whether there are any solution to handle such a case please?
If the need is to have a different logic based on whether the multi-instance activity being approved by all or by only some then I recommend to go with something similar to @Niall’s solution
Thanks a lot for your great advice. I’ve got the idea that the solution works in the case of approved by all (the condition event to check whether a variable set to be false when someone rejects in the user tasks). However, would you please expain something more detail about the case of majority pass (maybe 60% approved means approved).
Thanks a lot for your reference again. However, the solution uses a classic read-then-write pattern which may cause race consition on the same variable. Let’s say there are two person just try to complete their user task via REST call or Tasklist at the same time, and then two threads are created to execute to task complete listener. That’s exactly what I’m concerned with – (suppose yesVotes is 0 now) one thread read the yesVotes variable first, and then another thread read the same variable and write back its value plus 1(yesVotes is 1 now), finally the first thread write it back (it is still 1). You can say, in the condition, two person vote YES, but the yesVotes is 1 eventually.
UPDATED:
I’ve written a test to let a thread pool complete some task (nearly) at the same time. Then, a OptimisticLockingException was thrown which said Execution of 'UPDATE VariableInstanceEntity[27747ebd-afda-11ec-8304-9a41ae154892]' failed. Entity was updated by another transaction concurrently. Thus, may I consider that there is no race condition beacause of optimistic lock and what I should do is handle the exception and then let the failed user complete his task again?
Camunda uses Optimistic Locking for concurrency control so if completing a task leads to concurrent modification of data then OptimisticLockingException gets thrown.
Another solution came to mind which I did not try.
You can try using a service task (async before is ticked) following the multi-instance approval activity in which you can query historical data using the historyService, and as a result determine # of approves.
Below is a snip of the code used to query historical variable instances (assuming “approved” is the local variable name used in the multi-instance task) execution.getProcessEngineServices().getHistoryService().createHistoricVariableInstanceQuery().processInstanceId(execution.getProcessInstanceId()).variableValueEquals("approved", true).count();
This helps me great! I found it also works for parallel multi instance call activity, which could collect variables in subprocesses without the out mapping.