Duplicate Records on Rapid Save Clicks — How to Prevent Race Conditions?

0
Hi everyone, I have a entity with a id attribute. Initially, id was an AutoNumber, but I was still facing occasional duplicate records. Because of that, I switched to manual increment (retrieving the highest ID and adding 1 inside a microflow). By the way my application has many concurrent users.   My problem is when users click the Save button very quickly multiple times, duplicate id values are sometimes created. Additionally, the first record created in the workflow is incorrect.  I already tried handling it in a before commit microflow, but it doesn't fully prevent the issue under high concurrency.   How can I prevent this race condition?   Thank you for your help!    
asked
2 answers
0

Hello Miray Mutlu,

 

How time criticial is this ID, does the user need to know it immediately?

What you maybe can consider is using a TaskQueue, so all the commits of this entity are processed through this task queue.

More information about this you can find here:

https://docs.mendix.com/refguide/task-queue/

 

Hope this gives you some direction,

 

Good luck!

answered
0

Hi Miray,

 

It's sometimes hard to prevent duplicates, but Mendix has introcued some features over the years to prevent it. Most important ones are:

  • Validate first
    • Retrieve current version from database [id = $InputParameter] to verify if id hasn't been set already
  • Disabled during action
    • It's a button property which makes running the same microflow by the same user hard
  • Blocking progress-bar 
    • It's an advanced property of the button (in the microflow selection window), whics disables any user interaction while the microflow is running
  • Disable concurrent execution
    • It's a microflow property which prevents a specific microflow to be run concurrent, handy if a user is triggering a general flow, like a scheduled event, but not handy if it should be limited per input parameter. Applies for all users.
  • Commit in separate transaction
    • It's a separate Java Action in the community commons module which you can use to quickly update the database record, for example a timestamp "StartedGeneratingID" such that a long-running process can be started and other threads can read that timestamp already and skip regeneration.
  • TaskQueues
    • Even better than the commit is separate transaction, this will pick up a process in background with a queue size set. So having a single queue, you know for certain that the process can not run in parallel. There can be multiple tasks, but as long as the start of a task checks if it's still required, this is best for long-running flows.
answered