in the past we used the Activiti ProcessEngine (Version 5.2). After some time we noticed that sometimes incoming messages are not handled because no one was listening. Digging into that problem we noticed some timing issue. Our own ServiceTask sends a message (RabbitMQ, not important), the next step in the process is to wait for the answer. Sometimes the answer came so fast, that somehow the MessageEventSubscription was not set at that time (task not comitted).
We solved this by implementing a SendAndReceiveMessageTask, that registers a Subscription for a message, sent the outgoing message and then waited for the answer - which will always be caught by the process as the listener was registered early.
We are approaching Flowable 6 in a new project - so we are checking our legacy solution.
So my question is: How can be assured that we don’t lose message due to timing issues in the process engine or how to design such a process correctly (if this is sufficient)?
In Flowable 6 there is the triggerable option for a Service Task. This option will solve the racing condition problem and was introduced exactly for service tasks like yours (sending and receiving a message from an external system asynchronously).
we reviewed this solution but it was not working the way we expected. Somehow this approach is missing a mechanism to find the correct execution in a running process.
For example, in a process we have two waiting triggerable tasks. The external system might only know the process instance id. If the external system responds, we are able to map it to an execution with the API - but unsure which of the two waiting tasks should be triggered.
On the other hand, there is no way to find out, that there are triggerable tasks in a waiting state at all, am I right?
What we would need is a combination of Intermediate Message Catch Event and Triggerable. A task should wait until it is triggered by an external system. When the external system responds, we need to find out, if there is a waiting task by ProcessInstanceId and a, e.g., message (like in EventSubscription in Int. Message Catch Events - to distinguish n waiting tasks in the same process). If we found a waiting task, the message must be delivered to the specific task in the specific process instance. That is what we would have to manage on our own.
As doing this in one task might be easier to model for anon-technical person, we are now using the combination of a ServiceTask and IntermediateMessageCatchEvent to fulfill our requirements.
Maybe you can make this Triggerable approach a bit more powerful in the future.
Please reply, if should explain a bit more or you have another approach.
The idea is that in that triggerable service task you can send the executionId (the execution is the parameter you get in when implementing the behavior) to the external system. using that execution identifier, you can then trigger the process.
So if you have x number of them active in parallel, they would have a different execution and thus execution ids.
You can use the runtimeService#createExecutionQuery() to query for execution at a specific step in the process.
Yes - there is the idea to build in some automatic correlation. Not sure how it would look like though :-).
Currently, we are trying this approach by giving the executionId the external system.
Seeing the waiting tasks will work the way you mentioned, but I can’t see if the activity is already waiting or still inside the execute-step, am I right? Compared the message-catch-approach, a table where all truly waiting tasks are listed is more straightforward.