Reputation: 2665
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
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
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