We are facing an issue with Optimisticlocking errors while executing Call Activity in a multi instance config with following error.
org.activiti.engine.ActivitiOptimisticLockingException: ProcessInstance[1721502] was updated by another transaction concurrently
All the tasks are synchronous and exclusive.
This is happening randomly and mostly when process started by call activity finishes and tries to update the call activity task back about its completion.
After googling, I see we can configure “RetryInterceptor” to resolve this issue, but no documentation on how to set the same.
So there are no tasks marked as async=“true”? There are no user tasks in the process definition or boundary events? If really everything is synchronous you should not get an ActivitiOptimisticLockingException of course. Which database are you using? I’m looking for as much info as possible so we can try to reproduce the issue.
I can’t comment on Activiti Enterprise I’m afraid. But do you have upload fields in the user task forms?
Because this could lead to async attributes being added automatically to the BPMN XML.
Did you have a look at the deployed BPMN XML to be sure?
I understand this is not an Activiti forum, only reason I ask here is expecting a prompt response.
BTW, we are not using form to persist variables either on start of the process or user task.
Seems Activiti Enterprise doesn’t expose “executions” API, means couldn’t use ReceiveTask, so as an alternative we use UserTask, to send data request to external custom application(async api) in listener , which sends back response of receiving request. Then wait till external system set variables and complete the task.
We don’t have any exact test case to reproduce this scenario, but we had this issue few days back.
Probably external system was executing set variable/complete task API more than once, which might cause this issue.
About RetryInterceptor:
We tried to configure RetryInterceptor, but it is triggered only if exception occurs in Async task. Is it normal.
I am still finding a proper way to configure RetryInterceptor, appreciate if you can throw some light here.
Sure
Yes when the external system is invoking the API multiple times for the same process instance you could indeed get this OptimisticLockingException. Because only the first API call will be able to make changes to the process instance and the second simultaneous API call will have the wrong execution revision and throw an OptimisticLockingException.
The RetryInterceptor is not used by default by the Engine, but you can configure it as an additional CommandInterceptor. The AsyncExecutor is where retries are handled by default, but that’s only used for async jobs.
I think a better place to deal with the exception would be in the external application, because it needs to do a retry of the same call, in case an OptimisticLockingException occurs.
Another possibility would be to use queues to prevent the calls from being executed at the same time. We are thinking of ways to at least allow variable updates to happen simultaneous for a next version of the engine. But this is how it currently works.