So, it executes an activity (via a Java delegate) which invokes an external service asynchronously. Some time later, this service will invoke a callback to my service with results of that call (and I can correlate it with event the process instance is waiting for). As a side note, I’ve ran into a race condition where results arrive faster then Camunda subscribes to the event - but I don’t think there’s a workaround for that, I’ll just have to implement retries when correlating? In any case, then the results are processed by another activity (synchronously) and the process ends.
My question is: how can I make the thread starting the process instance execution wait until the process instance completes, one way or another? Brute force solution would be to just start polling for process state once the thread gets back from the Camunda call which creates the process, but that doesn’t seem elegant to me. Is there perhaps a better way to achieve what I need? Note that this app is running on multiple nodes, so it’s entirely possible that a different node will receive the callback, execute the event correlation and resume process instance execution.
In C7, the typical solution is to put a Parallel Split Gateway before your “Send”, and move your “Catch” into a parallel branch. Put a Parallel Join Gateway after the Send/Catch.
Then put an Async Before on the “Send” (and perhaps, in your case, an Async After)
It’s not clean or pretty, but for more users, it seems to work.
Thank you very much! I got the part about splitting/merging via a Parallel Gateway - will experiment with it ASAP, but from what I understand, no reason it should not work - event is subscribed to in a different execution, and the original execution will block at the second Parallel Gateway until the second execution moves past the message catch event. I don’t think I understand the part about the async continuations, though: wouldn’t adding “Async Before” on the “Send” return control to the caller as soon as it is reached, thus defeating the purpose of the split in the first place?
Oh, we both misunderstood then . Yes, the primary problem is to, essentially, create a synchronous facade for an asynchronous operation as cleanly as possible. As for async transitions, it makes sense - both transactions will require (more or less) the same time to complete, thus increasing the chance (but not giving a guarantee) that the correlation will work on the first attempt.
As I’d said, worst case, I’ll implement some form of polling for process state, but this seems pretty ugly, tbh.
Hmm… wouldn’t there still be a race condition? One execution will start to commit a transaction, the second will start the async call, and if the results from that call will come before transaction is committed (and thus subscription will become visible), there is still a chance it won’t correlate? Or does it commit at the parallel gateway, effectively moving the marker to the event immediately? Interesting, will have to run more tests.
I think that’s the reason for the Async Before on the service call…
---<+>--- (Async Before) Service Call ---<+>----- Process Result
\---------Catch Message -----------/
(Sorry, I don’t have access to my usual tools)
The Async before causes the the Catch Message to start up right away due to the commit to the DB. Since the Catch is waiting when the service call fires, eliminating the race condition.