4 ms·
Can this issue be prevented if we use the promo code as the table primary key or document ID?
by codenut 11y ago
Can this issue be prevented if we use the promo code as the table primary key or document ID?
- jaysh 11y agoThat won't be enough because the promo codes are shared amongst many users. If the promo code became the primary key, then only one user would be able to redeem it. If you introduced some combination of a user ID and promo code, then it won't prevent a race of one user firing many queries with different promo codes and stacking them up. It would, however, fix the original problem.
- some1else 11y agoA simple Discount domain model with validations: Class Discount belongs_to :promo_code belongs_to :customer belongs_to :order validates_presence_of :promo_code, :customer, :order validates_associated :promo_code validates_uniqueness_of :promo_code_id, :scope => [:customer_id, :order_id] end Limiting down to a single Promo-code per order: Class Discount # ... validates_uniqueness_of :order_id, :scope => :customer_id end
- gavingmiller 11y agoThis right here is the heart of race condition bugs, and is NOT race condition safe. When running multiple web servers and without a "validates_uniqueness_of" constraint on your database, multiple requests hitting multiple different web servers can claim multiple discounts for the same user. Problem only grows as your number of web servers grow!
- kawsper 11y agoRead the part "Concurrency and integrity" in the Rails documentation: http://apidock.com/rails/ActiveRecord/Validations/ClassMethods/validates_uniqueness_of http://apidock.com/rails/ActiveRecord/Validations/ClassMetho... You need to enforce the uniqueness in the DB.
- some1else 11y agoTherefore the only thing left to do is run the following migration: add_index :discounts, [:promo_code_id, :customer_id, :order_id], :unique => true