How to group multiple API calls initiated from REST endpoint into a transaction?

Hello,
we are using Camunda as a workflow engine and persistence backend for our webapp. Camunda is embedded into spring-boot app.
Currently, all user interactions are modeled as message events. As a response to user action, webapp initiates an HTTP request, which is handled by spring-mvc handler, which then calls
runtimeService.createMessageCorrelation.

Now, I’d like to do more processing when handling the user action:

  • read a variable;
  • change it;
  • store it in the execution;
  • proceed with the flow defined by the action (message).

I want those to be performed synchronously, in atomic manner - either fully successful, or an error is returned as a response to the HTTP request and the token remains where it was before the request.
Also, I’d like it to be performed in exclusive manner - no other executions of the process instance should run concurrently.

As I understand, all these wishes are automatically satisfied if everything is performed as a part of Java delegate, which is invoked from a task marked as “Asynchronous after” and “Exclusive”. But what kind of transactional behaviour happens when I call camunda from spring-mvc endpoint?

How can I make several Camunda calls one transaction performed exclusively when it is initiated from mvc handler?

Thanks
Andrius

IMO you can’t have the exclusive execution if you do it as the reaction to a http call i.e. on the MVC thread. IIUC “exclusive” works only if the action is executed by the job executor, i.e. within an asynchronous continuation. Even then I’m not sure that “exclusive” would do what you want since it only serialised actions within one instance and not across instances.

I think - I want exactly that - exclusive among all executions of a single process instance.

I have an idea - if I model the process like this:
Screenshot from 2021-02-06 15-52-44
and I set the “Perform user action” as “Asynchronous after” and “Exclusive”:

  • according to the Camunda docs, createMessageCorrelation, which creates “Action” event should run synchronously with “Perform user action”.
  • it should run exclusively with regards to other executions, because I set so. Despite the fact that it was invoked from HTTP. Won’t it?

Now I think I’ve understood your requirement better. IMO you don’t need the “wait for user action” step as it adds nothing to the waiting behaviour of the process (for an external observer). Indeed, if you mark the message event “Action” as “async after” then all the further processing will take place in a job and hence in a transaction. But it will be not the same thread that handles the MVC request. The MVC thread will end at the “async after” point, i.e. immediately after the message event. If you start a transaction in the MVC thread, it will not be used for executing the downstream actions.

What is exactly your problem? Do you see an unexpected behaviour?

No, I definitely do not want to mark “Action” as “async after” because that would start a new transaction in a new thread.

My idea is just the opposite:

  • if I add a Task “Perform user action” after the message event, and put the implementation of the actions into it instead of doing the implementation in the MVC handler before the createMessageCorrelation
  • I leave the “Action” event without any “async” checks
  • I put “async after” and “exclusive” on “Perform user action”
  • will then “Perform user action” be executed on MVC thread sychronously?
  • will it guarantee no other executions will jump in and mangle with the variables while “Perform user action” is in progress?

I’d like to perform several actions synchronously after user click and report if they were successful on UI.

I’m afraid that while the MVC thread reads a variable and uses its value to produce the new value, other execution of the same process instance changes and stores it. Now, when MVC thread stores its value, the changes of the other execution get overwritten like they never occurred.

Not yet. I have no implementation yet. I’m trying to understand implications of different models.

I’m not a big expert, but I’ll try.

Yes

I’m not sure but I think no. It might happen that some other job is being executed when the MVC request arrives. It will not be suspended until the job is completed, hence there will be two threads accessing (and possibly modifying) the process variables.

The concurrency problems you described may happen in processes with or without “MVC threads”. A process must just have two or more branches that might be executed in parallel. This is due to the memory model of camunda processes (all branches share the same state – if no special actions are taken, like local variables used). To avoid this, you have to take care that there are no two branches accessing (and modifying) the same variable. Or use local variables.

1 Like

Thank you, I’ll ask that particular question as a new thread: Will "Exclusive" prevent parallel execution started from HTTP request?