Mutex for ActiveRecord Model

ruby, ruby-on-rails-4

Solution

I found a gem Remote lock when searching for a solution for my problem. It is a mutex solution that uses Redis in the backend.

It:

- is accessible for all processes

- does not lock the database

- is in memory -> fast and no IO

The method looks like this now

def nasty
  $lock = RemoteLock.new(RemoteLock::Adapters::Redis.new(REDIS))
  $lock.synchronize("capi_lock_#{user_id}") do
    http_request_1
    http_request_2
    update_user
  end
end

Problem

My User model has a nasty method that should not be called simultaneously for two instances of the same record. I need to execute two http requests in a row and at the same time make sure that any other thread does not execute the same method for the same record at the same time. ``` class User ... def nasty_long_running_method // something nasty will happen if this method is called simultaneously // for two instances of the same record and the later one finishes http_request_1 // before the first one finishes http_request_2. http_request_1 // Takes 1-3 seconds. http_request_2 // Takes 1-3 seconds. update_model end end ``` For example this would break everything: ``` user = User.first Thread.new { user.nasty_long_running_method } Thread.new { user.nasty_long_running_method } ``` But this would be ok and it should be allowed: ``` user1 = User.find(1) user2 = User.find(2) Thread.new { user1.nasty_long_running_method } Thread.new { user2.nasty_long_running_method } ``` What would be the best way to make sure the method is not called simultaneously for two instances of the same record?

Original source

Related problems