Since Activiti has started to support asynchronous messages since 5.8, so I have implemented a 'retry' function for Activiti, user could start/restart a process instance from given activity, i.e. if a process instance is suspended at a activity, user could call this API to enable the process instance to restart from a given activity even though the activity has never run, here is the process logic(not 100% match with my code change):
1: get history process instance
2: get process definition
3: get all executions
4: get root execution(parent execution is null, if there are concurrent executions,IS_ACTIVE_=0,IS_CONCURRENT_=0,IS_SCOPE_=1)
5: get concurrent executions(IS_ACTIVE_=1,IS_CONCURRENT_=1,IS_SCOPE_=0), when concurrent execution runs to gateway activity, IS_ACTIVE_ will be 0
6: New ExecutionEntity for this activity
7: new MessageEntity for the newly created ExecutionEntity
8: New cancelJobsList object where to store those jobs need to be killed or cancelled.
9: check if given activity is on branch(outgoing transitions size > incoming transitions size)
10: if isActivityOnBranch = false
10.1: put all jobs into cancelJobsList
10.2: delete all executions
10.3: Newly ExecutionEntity.setConcurrent(false), setScope(true)
10.3: goto 11.3.3
11: if isActivityOnBranch = true
11.1: get all activities on the branch including the activities on head branch
11.2: check if root execution is existed
11.2: if isRootExecution is existed
11.2.1: if root execution has no children executions
11.2.1.1: delete the job entity of root execution
11.2.1.2: put the job id into cancelJobsList
11.2.1.3: root execution.setActive(false);execution.setConcurrent(false); execution.setScope(true)
11.2.1.4: goto 11.3.2
11.2.2: if root execution has children executions
11.2.2.1: get all concurrent executions except the execution whose activity is in the list in 11.1)
11.2.2.2: get none concurrent executions exception the executions in 11.2.1)
11.2.2.3: remove those executions from root executions
11.2.2.4: delete none concurrent executions
11.2.2.5: put the jobs of none concurrent executions to cancelJobsList
11.2.2.6: goto 11.3.2
11.3: if isRootExecution is not existed
11.3.1: New root execution, execution.setActive(false);execution.setConcurrent(false); execution.setScope(true);
11.3.2: Newly ExecutionEntity.setConcurrent(true);execution.setScope(false)
11.3.3: set the parent to newly root execution for the newly ExecutionEntity
11.3.4: save newly ExecutionEntity and MessageEntity
12: call job threads manager to cancel given jobs in cancelJobsList
13: return true
I am not sure if there is a plan for Activiti team to implement a feature like this, but I hope it could help those people who need this feature, I will discuss with our manager to decide whether or not share the code.
welcome any feedback.