jsharpe
jsharpe

Reputation: 2665

thread(?) database locking(?) in rails

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 do I ensure that I never have >= 50 registrations considering that I have more than one rails process running? Theoretically, isn't it possible that two requests come in virtually simultaneously, both run the if statement and see < 50 registrations is true and then both of them create a new registration?

Upvotes: 2

Views: 699

Answers (2)

Vitaly Kushner
Vitaly Kushner

Reputation: 9455

For your particular case, just ignore the problem :) I'm 99.99% sure you don't really care if you have 50 or 51 registrations :) In a more general case you need to employ some locking.

SELECT count(*) FROM registrations FOR UPDATE

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

unfortunately 'count' method of ActiveRecord::Base doesn't support the :lock parameter (hmm, why?). So you need to use count_by_sql. Try the following in 2 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 1st one that runs will stop at the 'press enter' stage, the 2nd one should block at the 'counting...' stage until you release the 1st.

Upvotes: 2

user177507
user177507

Reputation:

stored proc to create the row if < 50, or else return a fault code

Or!

Create a queue system that creates the accounts, ensuring one process is creating them at all times

Upvotes: 0

Related Questions