0

Inside a Rails 2.3.x application, I want to update a record every time users click on a specific link.

For eg. visiting www.sito.com/tracks/1 I update a record like this:

r = Record.find(params[:id])
r.views = r.views + 1
r.save

Here are my doubts:

  • If 2 users visit the link at the same time, what happen? Probably the app is already updating the record... but what happen to the second request?

UPDATE:

Using a combination of Optimistic Locking, I did this:

Added a "lock_version" column to Record table

Changed the code into this:

    Record.transaction do
        begin
          @record.update_attributes(:views => @record.views + 1)
        rescue ActiveRecord::StaleObjectError
          retry
        end
    end
Mich Dart
  • 2,352
  • 5
  • 26
  • 44
  • Your problem and possible solutions described [here](http://guides.rubyonrails.org/active_record_querying.html#locking-records-for-update). – Maxim Mar 03 '15 at 14:10
  • I think Pessimistic locking is what I was looking for. But I'm trying to understand how to implement it.. I can wrap the above instructions into a "Transaction" block, right? Then... if 2 requests come in, what happen? – Mich Dart Mar 03 '15 at 14:23
  • There is another consideration to be made.. what if the update instructions are made into a "render" view? I don't have an explicit "find"... but I render a collection and for every item I call "update_attributes" – Mich Dart Mar 03 '15 at 14:27

1 Answers1

0

It depends.

If you're lucky, both requests will process as normal, and the counter will be incremented twice.

In all likelihood, though, one or the other increments will be lost. The particular scenario you are looking at right now is described, formally, as a Race Condition, and is a standard complication in multithreaded applications.

Here is a good place to start:

How do I avoid a race condition in my Rails app?

Community
  • 1
  • 1
mcfinnigan
  • 11,442
  • 35
  • 28