2017-09-19 9 views
1

StoreReservationの2つのモデルが含まれている予約システムを検討しています。 Storemax_seatsReservationguests_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は、トランザクションがコミット。オーバーブッキング!!

洞察力を共有できれば、私は大変感謝しています。ありがとうございました。

答えて

-1

代わりにbefore_createを使用してみませんか?あなたはあなたのやり方をすることができますが、なぜあなたはあなたのデータベースにそれを書いて、必要がなければ例外を発生させるプロセスを開始したいでしょうか?

関連する問題