MismatchingMessageCorrelationException : Cannot correlate message ‘onEventReceiver’: No process definition or execution matches the parameters

Viewed 2999

We are facing an MismatchingMessageCorrelationException for the receive task in some cases (less than 5%)

enter image description here

The call back to notify receive task is done by :

protected void respondToCallWorker(
                    @NonNull final String correlationId,
                    final CallWorkerResultKeys result,
                    @Nullable final Map<String, Object> variables
    ) {
        try {
        runtimeService.createMessageCorrelation("callWorkerConsumer")
                      .processInstanceId(correlationId)
                      .setVariables(variables)
                      .setVariable("callStatus", result.toString())
                      .correlateWithResult();

        } catch(Exception e) {
            e.printStackTrace();
        }
    }

When i check the logs : i found that the query executed is this one :

select distinct RES.* from ACT_RU_EXECUTION RES inner join ACT_RE_PROCDEF P on RES.PROC_DEF_ID_ = P.ID_ WHERE RES.PROC_INST_ID_ = 'b2362197-3bea-11eb-a150-9e4bf0efd6d0' and RES.SUSPENSION_STATE_ = '1' and exists (select ID_ from ACT_RU_EVENT_SUBSCR EVT where EVT.EXECUTION_ID_ = RES.ID_ and EVT.EVENT_TYPE_ = 'message' and EVT.EVENT_NAME_ = 'callWorkerConsumer' )

Some times, When i look for the instance of the process in the database i found it waiting in the receive task

SELECT DISTINCT * FROM ACT_RU_EXECUTION RES WHERE id_ = 'b2362197-3bea-11eb-a150-9e4bf0efd6d0'

enter image description here

However, when i check the subscription event, it's not yet created in the database

select ID_ from ACT_RU_EVENT_SUBSCR EVT where EVT.EXECUTION_ID_ = 'b2362197-3bea-11eb-a150-9e4bf0efd6d0' and EVT.EVENT_TYPE_ = 'message' and EVT.EVENT_NAME_ = 'callWorkerConsumer'

I think that the solution is to save the "receive task" before getting the response for respondToCallWorker, but sadly i can't figure it out.

I tried "asynch before" callWorker and "Message consumer" but it did not work, I also tried camunda.bpm.database.jdbc-batch-processing=false and got the same results, I tried also parallel branches but i get OptimisticLocak exception and MismatchingMessageCorrelationException

enter image description here

Maybe i am doing it wrong

Thanks for your help

1 Answers

This is an interesting problem. As you already found out, the error happens, when you try to correlate the result from the "worker" before the main process ended its transaction, thus there is no message subscription registered at the time you correlate.

This problem in process orchestration is described and analyzed in this blog post, which is definitely worth reading.

Taken from that post, here is a design that should solve the issue:

example process

You make message send and receive parallel and put an async before the send task. By doing so, the async continuation job for the send event and the message subscription are written in the same transaction, so when the async message send executes, you already have the subscription waiting.

Although this should work and solve the issue on BPMN model level, it might be worth to consider options that do not require remodeling the process. First, instead of calling the worker directly from your delegate, you could (assuming you are on spring boot) publish a "CallWorkerCommand" (simple pojo) and use a TransactionalEventLister on a spring bean to execute the actual call. By doing so, you first will finish the BPMN process by subscribing to the message and afterwards, spring will execute your worker call. Second: you could use a retry mechanism like resilience4j around your correlate message call, so in the rare cases where the result comes to quickly, you fail and retry a second later.

Another solution I could think of, since you seem to be using an "external worker" pattern here, is to use an external-task-service task directly, so the send/receive synchronization gets solved by the Camunda external worker API.

So many options to choose from. I would possibly prefer the external task, followed by the transactionalEventListener, but that is a matter of personal preference.

Related