DEV Community

Victor Hazbun
Victor Hazbun

Posted on • Updated on

 

Best practices: Avoid race conditions 🚘💥🚗😰

Here are some scenarios and tips to combat race conditions.

Understanding Race Conditions

A computer program is like a horse race. The computer program does several things at the same time, similarly to how several horses run at the same time in a horse race. Each horse represents what is usually called a thread of execution. That way, one such thread may handle network communication, another one may be responsible for redrawing the user interface. In the case of a race condition, the application works properly if a given horse wins the race. For example, the application may work if horse number five wins, but it will crash if any other horse wins the race. Source https://simple.wikipedia.org/wiki/Race_condition.

Real Life Example: Many users booking the same room at the same time

Imagine you have a booking app, let's pretend you a have Room model. The rooms table stores the user_id.

class Room
  def assign_to_user!(user_id)
    self.user_id = user_id
    self.save!
  end
end
Enter fullscreen mode Exit fullscreen mode

It looks fine, right? Nope, if two users make the same reservation at the same time you are probably going to run into serious problems. Here is why..

The first user who submitted the form will open a database transaction and the second user who submitted a millisecond after opened another database transaction. Now we have two opened database transactions, the second transaction has overridden the first. That means, the first user has paid for the room but the second got it, LOL. Just imagine the two hosts discussing in the lobby, you will hear something like this: "No, I booked the room!".

To prevent this you can lock the Room table.

class Room
  def assign_to_user!(user_id)
    # This block is called within a transaction,
    # room is already locked.
    with_lock do
      self.user_id = user_id
      self.save!
    end
  end
end

Enter fullscreen mode Exit fullscreen mode

By locking the table, even if two requests happened at the same time the record won't be updatable UNTIL the DB lock is released, this is called "Pessimistic locking".

Use Pessimistic locking whenever you know this kind of things are most likely to happen in your app. See full documentation and examples here: https://api.rubyonrails.org/classes/ActiveRecord/Locking/Pessimistic.html

Other Scenarios

Here is a small list of cases where you should implement database locking to avoid unwanted race conditions.

  • Money transactions
  • Booking flights
  • Making reservations
  • Cryptocurrency transactions
  • Gambling

Conclusion & Next Steps

Think about which parts of your application deserve database locking, hopefully you can patch those areas so all your users have a great experience.

Please let me know if you have questions or want to chat about other kinds of database locking mechanisms like Optimistic Locking.

Top comments (2)

Collapse
 
idl3 profile image
Ernest

Thanks for the tip! There's a typo on the code snippet, I believe you wanted to type with_lock instead of with_block right? :)

Collapse
 
victorhazbun profile image
Victor Hazbun

Right! 😅

The AI Brief

AI generated git commit messages

Minimize the struggle of remembering what you just coded. AI-generated commits make it easier to manage projects and keep track of changes. The Nutlope/aicommits project demonstrates how AI can improve commit messages.

I open sourced an AI that creates any UI in seconds

Make AI-generated user interfaces a breeze. This open-source project harnesses the power of generative AI technologies like chatGPT to create versatile, quick, and intuitive UI components.

Use AI to commit like a PRO in 1 second

Upgrade your commit message game with AI. Boost your productivity by using ChatGPT to generate commit messages and avoid context switching. OpenCommit is an open-source library that helps you achieve this easily.

Build your own ChatGPT starter kit

Train AI models on custom data for improved domain-specific knowledge. Combine the power of WebView technologies and this starter kit to train your ChatGPT model on specific websites, allowing for better-optimized outcomes.