Camunda 7: Multiinstance activity modification

Hi,

Is there any way to do below multiinstance activity modifications in camunda 7?

  1. Deleting started instance in multi instance activity. Ex- We have multi-instance loop and inside that we have sub process. We have 4 items in collection used in multiinstance for looping. All 4 instances are in running state and now i want to cancel one of the instance. But i want to make sure other 3 instances to get completed. and even multi-instance activity should get completed like normal way.

  2. Starting new instance but keep it in not started/suspended state. Take above example where multiinstance have triggered 4 instances and now i want to add one new instance. 5th instance should be added but should be in suspended or not started state. And after some other external event happened we want to triggere/start that 5th instance.

Thanks,
Pradip Patil

Hello my friend!

When you delete/cancel an “internal” instance of the multi-instance, you end up deleting the entire instance… since it is a “single execution” if I may say so.

A multi-instance is basically the execution of a “for loop”.

One of the multi-instance flows that I have in one of my projects, executes sequentially, and if any of the “internal instances” has a problem or incident, it will crash all the others… so I involved it in another subprocess internally within the multi-instance, and added a message event, which removes the “internal instance” from the execution and ends it in the state it is in… continuing the execution of the others.

So when you have a problem and need to end that “specific internal execution”, you can call the Camunda message correlate API, passing some exclusive multi-instance variable for correlation… like the “loopCounter”.

Try something like my example model below, and see if it meets your needs!

I hope this helps.

William Robert Alves

1 Like

Hi @Pradip_Patil, another possibility could be to use the process instance modification capabilities of the runtime service. The docs below talk about how this can be used to change multi-instance activities.

I’ve modelled an “add another task” process modification as a non-interrupting message catch event on the boundary of your multi-instance. The execution listener on the boundary event looks like this:

import org.camunda.bpm.engine.runtime.ProcessInstance
import org.camunda.bpm.engine.RuntimeService

println "= Adding another task "

def runtimeService = execution.getProcessEngineServices().getRuntimeService()
def processInstanceId = execution.getProcessInstanceId()

runtimeService.createProcessInstanceModification(processInstanceId)
  .startBeforeActivity("loopThroughOrderItems")
  .execute()

process_instance_modification.bpmn (8.0 KB)

  • Each “Do work” script task of the multi-instance sleeps for about 15 seconds simulating some work
  • After starting an instance of the process you can correlate the “add another task” message to your process instance. I used the REST API:
    curl -X POST "http://localhost:8080/engine-rest/message" -H "Content-Type: application/json" -H "Authorization: Basic yourdigesthere” -d '{ "messageName": "addAnotherTask", "businessKey": "1234"}'
    
  • I added some logging to show what is happening. I had to change some of the async settings to get the multi-instance instance to truly run in parallel.
    • The multi-instance body is marked as async-before and non-exclusive
    • The sub-process end event is marked as async-after and non-exclusive based on the advice from @thorben in this thread to reduce the amount of rollback if an optimistic locking exception is thrown when instances of the the multi-instance complete. I’d recommend playing with the async settings to see the impact on the logging - it is really interesting.
    • I’ve also added some randomness (+/- 4 seconds) to how long each “Do work” task runs
  • Side note, only 3 script tasks are runing in parallel because the default thread pool size for the job executor is 3 (I think). If you are running with a larger thread pool, you may see more concurrency.

Loop cardinality is 4, 2 new tasks were added, Tasks are numbered 0-5 inclusive:

= Starting ===============================
Started task 0
Started task 2
Sleeping for 14793 milliseconds
Started task 1
Sleeping for 18644 milliseconds
Sleeping for 11034 milliseconds
= Adding another task 
= Adding another task 
Finished task 1 after 11034 milliseconds
Started task 3
Sleeping for 16491 milliseconds
Finished task 0 after 14793 milliseconds
Started task 4
Sleeping for 16267 milliseconds
Finished task 2 after 18644 milliseconds
Started task 5
Sleeping for 11307 milliseconds
Finished task 3 after 16491 milliseconds
Finished task 5 after 11307 milliseconds
Finished task 4 after 16267 milliseconds
= Finished ===============================

Now a disclaimer :smiley: In the docs there is this …

But, “not recommended” != “don’t”. To me, this is quite a clean and readable solution, but I’d value feedback from others about the safety of this approach for this use case.

Hope that gives you some other ideas!

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.