Gateway parallel problem

Hi,
I’m using Flowable 6.6
I have problem with simple gateway example(source code below). I use parallelgateway which splits path to two paths and then I have simple script task with (flowable:async=“true” flowable:exclusive=“false”), and during ending second I’m getting FlowableOptimisticLockingException. Ofcourse after some time this script task is repeated which is bad beacause my transaction is commited (imagine adding order twice).
I could use exclusive=“true” but then is even worst beacause I’m getting Timeout trying to lock table “ACT_RU_EXECUTION”; SQL statement:
select * from ACT_RU_EXECUTION where ID_ = ? [50200-176] and this task is not even repeated or in deadjob

How to resolved this problem??

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:streamsoft="http://flowable.org/streamsoft" xmlns:flowable="http://flowable.org/bpmn" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef">
  <process id="gateway" name="Gateway example" isExecutable="true">
    <startEvent id="start"></startEvent>
    <userTask id="usertask1" name="User Task 1" >
    </userTask>

    <parallelGateway id="parallelgateway" name="Parallel Gateway"></parallelGateway>
    <scriptTask id="scriptTask2" name="scriptTask2" flowable:async="true" flowable:exclusive="false" scriptFormat="groovy" >
     <script>
     	println 'Start scriptTask2'
     	Thread.sleep(5000)
     	println 'Stop scriptTask2'
     </script>
    </scriptTask>
    <scriptTask id="scriptTask3" name="scriptTask2" flowable:async="true" flowable:exclusive="false"  scriptFormat="groovy">
     <script>
     	println 'Start scriptTask3'
     	Thread.sleep(5000)
     	println 'Stop scriptTask3'
     </script>
    </scriptTask>
        <scriptTask id="scriptTask4" name="scriptTask2" flowable:async="true" flowable:exclusive="false"  scriptFormat="groovy">
     <script>
     	println 'Start scriptTask4'
     	Thread.sleep(5000)
     	println 'Stop scriptTask4'
     </script>
    </scriptTask>
        <scriptTask id="scriptTask5" name="scriptTask2" flowable:async="true" flowable:exclusive="false"  scriptFormat="groovy">
     <script>
     	println 'Start scriptTask5'
     	Thread.sleep(5000)
     	println 'Stop scriptTask5'
     </script>
    </scriptTask>
    <parallelGateway id="parallelgateway2" name="Inclusive Gateway"></parallelGateway>
	<endEvent id="stop"></endEvent>

    <sequenceFlow id="flow1" sourceRef="start" targetRef="usertask1"></sequenceFlow>
    <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="parallelgateway"></sequenceFlow>
    <sequenceFlow id="flow3" sourceRef="parallelgateway" targetRef="scriptTask2"></sequenceFlow>
    <sequenceFlow id="flow4" sourceRef="parallelgateway" targetRef="scriptTask3"></sequenceFlow>
    <sequenceFlow id="flow5" sourceRef="scriptTask2" targetRef="scriptTask4"></sequenceFlow>
    <sequenceFlow id="flow6" sourceRef="scriptTask3" targetRef="scriptTask5"></sequenceFlow>
    <sequenceFlow id="flow7" sourceRef="scriptTask4" targetRef="parallelgateway2"></sequenceFlow>
    <sequenceFlow id="flow8" sourceRef="scriptTask5" targetRef="parallelgateway2"></sequenceFlow>
    <sequenceFlow id="flow9" sourceRef="parallelgateway2" targetRef="stop"></sequenceFlow>

  </process>
</definitions>

Hi Mirek,

flowable:exclusive=“false” allows to run script tasks in parallel. That’s why when join parallel gateway can be executed in parallel and OptimisticLockingException can occur.

My guess for flowable:exclusive=“true” is that Thread.sleep(...) are so long that the last thread is time-outed. To be sure I have to debug the case.

If you want to run script tasks in parallel I would make join parallel gateway async to avoid OptimisticLockingException rollback and repeating whole execution again.

Regards
Martin

Thanks for replay,
When I added async to joining parallel gateway problem was solved. But still I would like make exclusive=“true” to work.

I understand how excluise should works but I don’t undestand why is throwing exception. It should works like: async executor should check if another task in this process instance is not currenlty procesed then add his job to the execution table. Even If the exception occured then async executor should retry job execution. Now is in strange state is in job store (processEngine.getManagementService().createJobQuery().list()) but no processing anymore.

I’m waiting for your conclusions from debugging

I have some news, today I checked on our testing/production database PostgreSQL and problem with locking and “exclusive” didn’t occur. So exception under is only H2 specific

Timeout trying to lock table "ACT_RU_EXECUTION"; SQL statement:
select * from ACT_RU_EXECUTION where ID_ = ? [50200-176]
	at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:149)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:76)
	at org.flowable.common.engine.impl.db.DbSqlSession.selectById(DbSqlSession.java:306)
	at org.flowable.common.engine.impl.db.AbstractDataManager.findById(AbstractDataManager.java:71)
	at org.flowable.engine.impl.persistence.entity.data.impl.MybatisExecutionDataManager.findById(MybatisExecutionDataManager.java:97)
	at org.flowable.engine.impl.persistence.entity.data.impl.MybatisExecutionDataManager.findById(MybatisExecutionDataManager.java:51)
	at org.flowable.common.engine.impl.persistence.entity.AbstractEntityManager.findById(AbstractEntityManager.java:42)
	at org.flowable.engine.impl.cfg.DefaultInternalJobManager.handleJobInsertInternal(DefaultInternalJobManager.java:76)
	at org.flowable.job.service.ScopeAwareInternalJobManager.handleJobInsert(ScopeAwareInternalJobManager.java:56)
	at org.flowable.job.service.impl.persistence.entity.JobEntityManagerImpl.doInsert(JobEntityManagerImpl.java:51)
	at org.flowable.job.service.impl.persistence.entity.JobEntityManagerImpl.insert(JobEntityManagerImpl.java:46)
	at org.flowable.job.service.impl.persistence.entity.JobEntityManagerImpl.insert(JobEntityManagerImpl.java:31)
	at org.flowable.common.engine.impl.persistence.entity.AbstractEntityManager.insert(AbstractEntityManager.java:52)
	at org.flowable.job.service.impl.asyncexecutor.DefaultJobManager.unacquire(DefaultJobManager.java:346)
	at org.flowable.job.service.impl.asyncexecutor.ExecuteAsyncRunnable$3.execute(ExecuteAsyncRunnable.java:213)
	at org.flowable.job.service.impl.asyncexecutor.ExecuteAsyncRunnable$3.execute(ExecuteAsyncRunnable.java:210)
	at org.flowable.engine.impl.interceptor.CommandInvoker$1.run(CommandInvoker.java:59)
	at org.flowable.engine.impl.interceptor.CommandInvoker.executeOperation(CommandInvoker.java:107)
	at org.flowable.engine.impl.interceptor.CommandInvoker.executeOperations(CommandInvoker.java:81)
	at org.flowable.engine.impl.interceptor.CommandInvoker.execute(CommandInvoker.java:64)
	at org.flowable.engine.impl.interceptor.BpmnOverrideContextInterceptor.execute(BpmnOverrideContextInterceptor.java:26)

H2 has a simpler table locking mechanism compared to H2, so that’s most likely the explanation.