(?) database lock (?) in rails

Let's say I have this method:

def create_registration_unless_over_limit
  if Registration.count < 50
    Registration.create!
  else
    raise "too many registrations"
  end
end

      

How can I ensure that I never have> = 50 registrations given that I have more than one rail running? In theory, it is not possible that two requests arrive almost at the same time, both run an if statement and see <50 registrations are true, and then both create a new registration?

+2


source to share


2 answers


In your particular case, just ignore the problem :) I'm 99.99% sure you don't care if you have 50 or 51 registrations :) More generally, you need to use some kind of locking.

SELECT count(*) FROM registrations FOR UPDATE

      

the above request will block if another thread has executed it and is still inside a transaction.



Unfortunately, ActiveRecord :: Base's counting method does not support the: lock (hmm, why?) Parameter. Therefore you need to use count_by_sql. Try the following on two separate terminal screens:

./script/runner 'Registration.transaction {puts "counting...";c = Registration.count_by_sql("select count(*) from registrations for update");puts "count = #{c}. press enter to continue";gets}'

      

while the first one that starts will stop at the "press enter" stage, the second one should block at the "counting ..." stage until you release the 1st.

+2


source


saved proc to create string if <50, otherwise return error code

Or



Create a queue system that creates accounts, ensuring that one process creates them at any time

0


source







All Articles