cancel
Showing results for 
Search instead for 
Did you mean: 

Modelling an async user wait on a long running service task.

alistairb
Champ in-the-making
Champ in-the-making
Hi,

I have a scenario where I have long running evaluation service task (Java Delegate) that I need to run asynchronously so that I can provide user feedback experience, i.e. a spinner in a web application, whilst waiting for the service task to complete.  Having seen the parallel gateways feature, combined with async=true and exclusive=false, I thought I had the tools to model this behaviour in BPM. 

I'm using Activiti 5.9 (and have tried 5.10 also) and launching the the default Activiti job executor but there appears to be some form of race condition as when polling for completion of the evaluation service, it appears to wait 5 minutes before executing the job(service) and I then end up with stale process instance variables beyond the continuation of this sub-process.  I've spent some time experimenting with different combinations of async/exclusive settings etc, but without success. 

I guess I'd like to clarify whether I'm modelling this process incorrectly in BPM terms as it must be a very common scenario for users of web based applications interacting with a process; For standard interaction the user makes a request to the server, and waits for the next user task, with Activiti determining the next user task to route to via the process definition.  In this case with it being a long running task, the user needs to be redirected somewhere where they are informed the task is in progress, and modelling a parallel process seemed like a logical approach as I could create a page, spinning of a polling action and then transition to complete the user task when the job has finished.

If there are any recommended approaches/patterns to follow then I'd be very grateful to hear about them.

Many thanks

Alistair
9 REPLIES 9

frederikherema1
Star Contributor
Star Contributor
When you have long-running tasks executed by the job-executor, you should consider that:

  • Executing a service-task (or any other task) keeps a transaction open until a wait-state/process-end/async-task is reached. If you have long-running operations, make sure your DB doesn't time out.
  • When a jobs is running for 5 minutes, the job aquisistion-thread assumes the job-executor that was running the job, has either died or has failed. The lock of the job is removed and the job will be executed by another thread in the executor-pool. This timeout-setting can be  raised, if that is required.
  • Long-running tasks modeled IN the activiti-process always keep a transaction open and a job-executor thread occupied. Better practice is to use a queue-signal approach where the long-runnin operation is executed outside of activiti (queued to eg. camel using a service-task, providing the neccesairy variables needed alongside). When the long-running task is completed, it should signal the execution, which has a recieve-task modeled in.

Frederik Heremans wrote:

When you have long-running tasks executed by the job-executor, you should consider that:

  • Executing a service-task (or any other task) keeps a transaction open until a wait-state/process-end/async-task is reached. If you have long-running operations, make sure your DB doesn't time out.
  • When a jobs is running for 5 minutes, the job aquisistion-thread assumes the job-executor that was running the job, has either died or has failed. The lock of the job is removed and the job will be executed by another thread in the executor-pool. This timeout-setting can be  raised, if that is required.
  • Long-running tasks modeled IN the activiti-process always keep a transaction open and a job-executor thread occupied. Better practice is to use a queue-signal approach where the long-runnin operation is executed outside of activiti (queued to eg. camel using a service-task, providing the neccesairy variables needed alongside). When the long-running task is completed, it should signal the execution, which has a recieve-task modeled in.

Hi,

I'm also running a long service-task, and would like to raise the job execution timeout as Frederik Heremans suggested.

Does anyone (Fredeik?) know how to do it? I can't find any documentation for this.

Thanks,

Aviran

asyncExecutorSecondsToWaitOnShutdown
https://www.activiti.org/userguide/6.latest/#_async_executor_configuration

ProcessEngineConfigurationImpl.setAsyncExecutorSecondsToWaitOnShutdown

Activiti/ProcessEngineConfigurationImpl.java at master · Activiti/Activiti · GitHub 

public ProcessEngineConfigurationImpl setAsyncExecutorSecondsToWaitOnShutdown(long asyncExecutorSecondsToWaitOnShutdown) {
    this.asyncExecutorSecondsToWaitOnShutdown = asyncExecutorSecondsToWaitOnShutdown;
    return this;
}

andreibica
Champ in-the-making
Champ in-the-making
I'm also trying to model a long operation followed by a result which must be feed into the workflow. For this I am using a Java Service Task to initiate the operation and a Java Receive Task to wait for the result. The problem that I see here is that the result of the operation may come faster then the engine is reaching the Java Receive Task. In this case if I am trying to signal the process when I receive the result I will get an exception because the process is not in waiting state.

Is there a way to avoid this problem or am I missing something?

Thanks,
Andrei

We are solving this by using only one service task for send and receive that is a spring @Component extending ReceiveTaskActivityBehavior. In the execute() you start your async processing storing your executionId, when finished just triggering that executionId.   

(This works, but I'm not sure this is really the proper way, because Activiti doc says: don't extend ActivitiBehavior just if you know what you are doing.)   

jbarrez
Star Contributor
Star Contributor
Hmmm I'm afraid such a problem can only be resolved by putting a queue in front of the service which checkes whether the process is in the correct state and delivers the message only if it's true.

andreibica
Champ in-the-making
Champ in-the-making
And this kind of checks should be done periodically?
Do I have a clue when I should do this kind of checkups so I don't need to pull them periodically?
In case that the state of the workflow is changed by a call comming from a thread from JobExecutor (e.g. because a timer has expired) then I don't have any clue when the process arrives in a wait state.
Is this correct?

jbarrez
Star Contributor
Star Contributor
> Do I have a clue when I should do this kind of checkups so I don't need to pull them periodically?

Use regular queue implementations (jms is a bit heavy, but something like hazelcast queue or something of Spring …)

>  then I don't have any clue when the process arrives in a wait state.

True. But you can always query for the state of all your processes.

ksgphellow
Champ on-the-rise
Champ on-the-rise

I have a similar Question.

I would like to model a Process for a Questionnaire, so someone assigns the questionnaire, and the assignee has to fill that out.  If the Questionnaire is not filled in 5 days I'll send him a reminder and so on.

Is this too longterm to model in Activiti or is that viable?