Skip to content

Commit

Permalink
close #2156: lock db when generate bib_index to fix concurrency
Browse files Browse the repository at this point in the history
  • Loading branch information
hengsokly committed Dec 20, 2024
1 parent 15a4239 commit 974c2f4
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 11 deletions.
19 changes: 9 additions & 10 deletions app/models/spree_cm_commissioner/guest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -180,23 +180,22 @@ def bib_display_prefix?
end

def generate_bib
return if bib_prefix.present?
return unless bib_required?
return if event_id.blank?
return if bib_prefix.present? || !bib_required? || event_id.blank?

self.bib_prefix = line_item.variant.bib_prefix
self.class.transaction do
rows = self.class.where(event_id: event_id, bib_prefix: line_item.variant.bib_prefix).lock
last_bib_number = rows.map(&:bib_number).max || 0

last_bib_number = event.guests
.where(bib_prefix: bib_prefix)
.maximum(:bib_number) || 0
self.bib_prefix = line_item.variant.bib_prefix
self.bib_number = last_bib_number + 1
self.bib_index = "#{event_id}-#{bib_prefix}-#{bib_number}"

self.bib_number = last_bib_number + 1
self.bib_index = "#{event_id}-#{bib_prefix}-#{bib_number}"
save!
end
end

def generate_bib!
generate_bib
save!
end

# bib_number: 345, bib_prefix: 5KM, bib_zerofill: 5 => return 5KM00345
Expand Down
18 changes: 17 additions & 1 deletion spec/models/spree_cm_commissioner/guest_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,6 @@
end
end


context "when guest in the same event" do
context "when guest has the same prefix" do
let(:line_item) { create(:line_item, order: order, variant: product_with_bib1.variants.first) }
Expand All @@ -327,6 +326,23 @@
end
end

context "when multiple generate_bib! concurrently" do
let(:line_item) { create(:line_item, order: order, variant: product_with_bib1.variants.first) }
let(:guest1) { create(:guest, line_item: line_item, seat_number: 1) }
let(:guest2) { create(:guest, line_item: line_item, seat_number: 2) }
let(:bib_prefix) { line_item.variant.bib_prefix }

it 'ensures unique bib_numbers and bib_index for each guest' do
threads = []
threads << Thread.new { guest1.generate_bib! }
threads << Thread.new { guest2.generate_bib! }
threads.each(&:join)

bib_indices = SpreeCmCommissioner::Guest.where(event_id: guest1.event_id, bib_prefix: bib_prefix).pluck(:bib_index)
expect(bib_indices.uniq.size).to eq(2)
end
end

context "when guest has different prefix" do
let(:line_item1) { create(:line_item, order: order, variant: product_with_bib1.variants.first) }
let(:line_item2) { create(:line_item, order: order, variant: product_with_bib1.variants.last) }
Expand Down

0 comments on commit 974c2f4

Please sign in to comment.