2017-09-19 1 views
1

Nous envisageons un système de réservation où il y a deux modèles impliqués: Store et Reservation. Store a max_seats et Reservation a guests_count colonne.Éviter les sur-réservations en raison des conditions de course

Pour éviter la surréservation, nous avons implémenté la validation. En cas de surréservation, la transaction est annulée. Mais je ne sais pas si cela est assez infaillible contre les conditions de course.

comme ceci:

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 

Je soupçonnais ce scnenerio peut encore se produire, même si elle est rare:

On suppose que A et B client clients font une réservation de 6 sièges individuellement, max_seats est défini sur 10. Si la transaction du client A est validée avant que le client B exécute le rappel after_create, l'exception ActiveRecord::Rollback est déclenchée et l'enregistrement du client B n'est pas créé, ce qui est prévu. Cependant, si le rappel after_create est effectué avant la validation de la transaction du client A, je pense qu'il en résultera une situation de surréservation.

A commence transaction -> A effectue after_create -> A commet transaction -> B effectue after_create: B rencontre ActiveRecord::Rollback exception

A commence transaction -> A effectue after_create -> B effectue after_create -> A commet transaction: Surréservation!!

Si vous pouviez partager des idées, je l'apprécierais grandement. Je vous remercie.

Répondre

-1

Pourquoi ne pas simplement utiliser un before_create à la place? Vous pouvez le faire à votre façon, mais pourquoi voudriez-vous commencer à l'écrire dans votre base de données et déclencher une exception si vous n'en avez pas besoin?