How to disallow concurrent execution or apply locking till the end of a database transaction?
In our application we need a way to prevent a microflow (which commits to the database) from starting again untill the database transaction of the same already running microflow has completely ended. This is because in our case it will result in wrong results when the same microflow is called before the whole transaction of the previous microflow call has been written to the database. The documentation of the 'Disallow Concurrent Execution' property only describes that the microflow cannot be execued more than once concurrently, and therefore does does not quarantee anything about the transaction. We did some experiments with 'locking' (using the CommunityCommons functions) from a microflow which commits to the database (eg within the microflow itself, in a before commit and in an after commit). We found out that the lock is always removed before the after commit ends and therefore before the transaction has been completed. What is the Mendix way to make sure that a microflow can only be started when the database transaction of the same but previous microflow call has been completely finished?
Creating locks on a DB isn't always the best solution.
I would recommend a Queueing mechanism instead. This however depends on the scope of the transaction of that microflow. If all the changes are inside the microflow, then Queuing makes more sense.
I use the Vert.x work queue for that, using a custom MxObject -> JSON serializer to pass parameters to the microflow you want to queue.
Could you not use a boolean that the microflow checks to see if it may go on running? Then at the end of the already running microflow you could trigger a RunMicroflowAsyncInQueue to set the bollean back so a next microflow is allowed to run. This way the current microflow can end its transaction while another microflow handles the resetting of the boolean.
You may achieve what you want by using the EndTransaction Java action from community commons, at least you can use this to end a transaction before a microflow ends (I am not sure if you must also call StartTransaction afterwards if you need to start a new one, or if that happens automatically).
You could also wrap the call to the microflow in a Java action that contains a synchronized block.
Or you could implement your own in memory Java locking mechanism using semaphores.