Store
とReservation
の2つのモデルが含まれている予約システムを検討しています。 Store
はmax_seats
、Reservation
はguests_count
の列を有する。レースコンディションの結果として過剰予約を避ける
オーバーブッキングを避けるため、検証を実装しました。オーバーブッキングの場合、トランザクションはロールバックされます。しかし、これが競争条件に対して十分に安全かどうかは不明です。
そのよう:
は、顧客Aと顧客Bは個別に6席の予約をしていると仮定します。私はこのscnenerioはまだそれは稀だろうにもかかわらず、発生する可能性が疑うのです
class Store < ActiveRecord::Base
has_many :reservations
validates :max_seats, presence: true, numericality: true
end
class Reservation < ActiveRecord::Base
belongs_to :store
validates :guests_count, presence: true, numericality: true
after_create do
total_seats_taken = reservation_slot.reservations.sum(&:guests_count)
unless total_seats_taken <= store.max_seats
raise ActiveRecord::Rollback
end
end
end
顧客Bがafter_create
コールバックを実行する前に顧客Aのトランザクションがコミットされた場合、ActiveRecord::Rollback
例外が発生し、顧客Bのレコードが作成されないことが意図されています。ただし、顧客Aの取引がコミットされる前にafter_create
コールバックが実行されると、オーバーブッキングの状況になると考えられます。 > B after_create
行う - - - > A after_create
が実行B遭遇ActiveRecord::Rollback
例外
Aは、トランザクションが開始> Aはトランザクションをコミット:
Aがトランザクションを開始 - > Aが実行after_create
- > Bはafter_create
が実行 - > Aは、トランザクションがコミット。オーバーブッキング!!
洞察力を共有できれば、私は大変感謝しています。ありがとうございました。