Store process instance state for synchronous process explicitly

I have some process, which triggered from Front-End (FE) rest call. This process consists of calls to other services. Of course, something can go wrong during this actions and in that case I need to rollback changes that I already made. Because process started by FE, it should be syncrhonous, so I should respond when process finished/failed and not while it’s still in progress. The rollback procedure may start in the background and be asynchronous, one reason for it is retry mechanism.

So, it seems like I need to use external compensation (rollback as separate process, started when original process caught an error). But I’m worried about restart-safety of this process. My process is synchronous and doesn’t have wait states, so BMPN engine didn’t save state to the database. And if service with BMPN engine will die, rollback process will not be started, but changes to external services have already done. Also it seems like even history db doesn’t contain any information about this process instance. So I can’t rollback this changes. How can I work around this problem?

My idea is to add explicitly saving of process states. I know, that if the process will be asynchronous, BMPN engine will save state before each transaction. But it’s not suitable for me. It will be great if I just can tell BPMN engine to save state and continue the process, but I don’t think it’s possible. Another idea is to add listener after/before each service task and save state by myself. Also, I need to implement some cron job, which will search for "died’ process (not updated for some configurable duration) and start rollback process for them.

What is the best way to handle this problem?

1 Like

Hi, what´s the tecnologies that you work?
if you really need to response synchronous you can create a polling process using a java.util.concurrent.ExecutorService. but it´s important to configure timeout on this process, to put timer event in your modeling, to create a BpmnError when runtime error ocurrs and to monitor the bpm incidents and not just tasks;

Hi, thanks for your reply. We use spring boot microservices. But FE is an external customer software which will use our API.
Unfortunately, it’s not desirable for us to put such polling logic to every endpoint which we want to expose. Also, I don’t think this solution will help with restart safe - if the service will die, it will not create any incident, and still doesn’t store any information of the process instance

Hi @Dmitriy_Stoyanov,

maybe this example helps you out: https://github.com/camunda-consulting/code/tree/master/snippets/async-on-error

Hope this helps, Ingo

I actually thought about exposing a synchronous API to the frontend that would do the polling. As an evolution, this synchronous control can be worked using a message stream like kafka (all events will be logged). Where the entire frontend request could go to a topic that would be consumed and processed by the engine.

Thanks, looks interesting!
This example will help with async error handling. But still, I want to add some savepoints, because error handling will not work if service will just terminated in the middle of process. And will not be restarted/rollbacked.
Maybe there is some method in internal API that allows to call save state of activity?

Hi @Dmitriy_Stoyanov,

With this use case you cannot use async continuation, as you won’t get the response when the process is successful or failed.

The benefit of the example is to add the async waitstate on demand, only if the service task(s) failed. I haven’t checked, but I assume that this will work on the sequence of service tasks as well and creates the async continuation only for the failed task. But you should check it with a chain of service tasks by yourself.

Hope this helps, Ingo

Sure, async continuation only for error case.

Yeah, it’s work for sequence, I checked. If task fails, it will be retried even if service is restarted. But if service stopped before task is failed, engine will not start retry of activity

Anyway, thank for you help

Good evening again.

This example actually help me in rollback process. But I have some trouble - I couldn’t change failed job retry cycle. I changed global retry cycle adding plugin to engine configuration and it’s working for process definitions with asyncBefore.
But for process with synchronous actions wrapped in AsyncOnErrorActivityBehavior retry not changed. So, tasks are retried 3 times without any delay.

Could you help me, how can I configure retry interval?

Hi @Dmitriy_Stoyanov,

you can set the dueDate and the retries manually on the message in the AsyncOnErrorActivityBehavior.createAsynchronousContinuationJob() method to delay the service execution.

Hope this helps, Ingo

1 Like