Parallel start of CaseExecutions causes OptimisticLockExceptions

Hi Folks,

I have an issue with my case implementation. If, at the same time, two threads are trying to start activities for the same case instance, using caseService.manuallyStartCaseExecution(...), one of them will fail with an OptimisticLockException.

The id in the stacktrace points to the CaseExecutionEntity which is the CaseInstance itself, so to me it seems, that each time a CaseExecution is started, the CaseInstance is updated. As far as I can see, only the revision is incremented.

Any idea why this update is necessary and how I can work around this?

Cheers,
Stefan

Hi Stefan,

This is expected behavior. The general pattern is (similar for BPMN execution): Whenever the set of child executions of an execution changes (children added or removed), then the execution itself must be updated. This avoids inconsistencies, e.g. when the remaining two child executions are completed in parallel, the last one completing must terminate the parent.

The way to deal with this is the same for every OptimisticLockingException: Retry the failing API command.

Cheers,
Thorben

Hi Thorben,

I was afraid it is like that. We will start synchronizing some parts of our internal API and hope it won’t become a bottleneck :slight_smile:

Cheers!
Stefan

@thorben

I need to come back at this. We have now implemented a small retry around the call to caseService which runs inside our transaction, as we are using Camunda embedded into our SpringBoot app.

We are easily able to start the case execution this way, but in the end our transaction fails, because Spring marked it as RollbackOnly when Camunda threw the OptimisticLockingException (which is a RuntimeException)in the first place.

Any ideas how I can overcome this? I read of Spring’s noRollbackForClassName but I am a little afraid of opening that door and it is not really an option because I have to annotate it on every transactional method that calls the CaseService…

Cheers,
Stefan

Hi Stefan,

The engine’s transaction must indeed be rolled back. OptimisticLockingException is thrown when the engine flushes its entity cache to the database. That means, it can be that on the fifth out of ten UPDATE statements, an optimistic locking exception is thrown because the update could not be applied. In this case, the four prior updates must be rolled back. Thus, the engine’s transaction must be rolled back.

There are two solution ideas that come to mind:

  1. Use a nested transaction for things that the engine does so that they can be rolled back without rolling back the outer transaction. I have no experience with this, though, and we do not test such a thing in any way.
  2. Apply the retry mechanism outside of the transaction, i.e. pull up the try-catch clause.

Cheers,
Thorben