Start process instance locks DB

Hello,

I have a Service- A which makes an api (feign client) call to Service-B (Flowable service) with its own DB, to start a process instance by a given definition key and return the instance id to Service-A to save it use it for later processing (within Service-A DB). However, I have noticed that when calls are made by diff users (Concurrently) at the same time to create the process instance, the api call made from Service-A to Service-B never returns and the api call times out.
When i took the thread dump, I noticed that one of the thread had locked the db record and hence subsequent call made will not be processed.

Below is the dump details.

            "http-nio-80-exec-617" Id=98363 cpu=52761177754 ns usr=51000000000 ns blocked 57 for -1 ms waited 1660 for -1 ms
   java.lang.Thread.State: RUNNABLE
	locks java.util.concurrent.ThreadPoolExecutor$Worker@20123d7a
	at java.base@11.0.6/java.net.SocketInputStream.socketRead0(Native Method)
	at java.base@11.0.6/java.net.SocketInputStream.socketRead(SocketInputStream.java:115)
	at java.base@11.0.6/java.net.SocketInputStream.read(SocketInputStream.java:168)
	at java.base@11.0.6/java.net.SocketInputStream.read(SocketInputStream.java:140)
	at org.postgresql.core.VisibleBufferedInputStream.readMore(VisibleBufferedInputStream.java:140)
	at org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:109)
	at org.postgresql.core.VisibleBufferedInputStream.read(VisibleBufferedInputStream.java:67)
	at org.postgresql.core.PGStream.receiveChar(PGStream.java:335)
	at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2000)
	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:310)
	- locked (a org.postgresql.core.v3.QueryExecutorImpl@780a08ae) index 9 frame org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:310)
	at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:446)
	at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:370)
	at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:149)
	at org.postgresql.jdbc.PgPreparedStatement.execute(PgPreparedStatement.java:138)
	at com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44)
	at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.execute(HikariProxyPreparedStatement.java)
	at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:46)
	at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:74)
	at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:50)
	at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
	at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185)
	at org.flowable.common.engine.impl.db.DbSqlSession.flushRegularInsert(DbSqlSession.java:442)
	at org.flowable.common.engine.impl.db.DbSqlSession.flushInsertEntities(DbSqlSession.java:426)
	at org.flowable.common.engine.impl.db.DbSqlSession.flushInserts(DbSqlSession.java:406)
	at org.flowable.common.engine.impl.db.DbSqlSession.flush(DbSqlSession.java:291)
	at org.flowable.common.engine.impl.interceptor.CommandContext.flushSessions(CommandContext.java:191)
	at org.flowable.common.engine.impl.interceptor.CommandContext.close(CommandContext.java:61)
	at org.flowable.common.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:80)
	at org.flowable.common.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:49)
	at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
	at org.flowable.common.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:46)
	at org.flowable.common.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:30)
	at org.flowable.common.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:56)
	at org.flowable.common.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:51)
	at org.flowable.engine.impl.RuntimeServiceImpl.startProcessInstanceByKey(RuntimeServiceImpl.java:117)

Below is the api code.

        @RequestMapping( value = "/rest/process-instances/{processDefinitionKey}", method = RequestMethod.POST )
            public ProcessInstanceRepresentation startNewProcessInstanceByprocessDefinitionKey( @PathVariable String processDefinitionKey,
                                                                                                @RequestBody ProcessInstanceVariable instanceVariables ) throws Exception
            {
                Map<String, Object> variables = instanceVariables.getPayload();
                log.info( "Starting process instance with definition id: {} with variables {} : ",
                          processDefinitionKey,
                          variables.toString() );
                try
                {
                    ProcessInstance lProcessInstance = runtimeService.startProcessInstanceByKey( processDefinitionKey, variables );
                    log.info( "Workflow process instance started successfully for def id: {} with instance id {}",
                              processDefinitionKey,
                              lProcessInstance.getId() );

                    ProcessInstanceRepresentation lProcessInstanceRepresentation = new ProcessInstanceRepresentation();
                    lProcessInstanceRepresentation.setProcessDefinitionKey( processDefinitionKey );
                    lProcessInstanceRepresentation.setProcessDefinitionName( lProcessInstance.getName() );
                    lProcessInstanceRepresentation.setId( lProcessInstance.getId() );
                    lProcessInstanceRepresentation.setProcessDefinitionDeploymentId( lProcessInstance.getDeploymentId() );
                    lProcessInstanceRepresentation.setProcessDefinitionVersion( lProcessInstance.getProcessDefinitionVersion() );
                    return lProcessInstanceRepresentation;
                }
                catch( Exception e )
                {
                    e.printStackTrace();
                    log.error( "Exception during starting process instance for key", processDefinitionKey );
                    throw new Exception( "Exception during starting process instance for key" + processDefinitionKey );
                }

            }

Should i make this call sequential so it just creates instances sequentially (may be make the endpoint synchronized) and return the instances id back to service A ?

Or

Can anyone suggest any better alternative for this ?

Thanks
Venkatesh

Starting process instances is independent from each other, they create their own data and that’s it. How does your model look like? Do you have async/exclusive steps maybe (still shouldn’t make a difference, though). Is there any data shared between the instances?