Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent 500 on parallel org quota creation #3924

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions app/models/runtime/quota_definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ class QuotaDefinition < Sequel::Model
:app_instance_limit, :app_task_limit, :total_service_keys, :total_reserved_route_ports,
:log_rate_limit

def around_save
yield
rescue Sequel::UniqueConstraintViolation => e
raise e unless e.message.include?('qd_name_index')

errors.add(:name, :unique)
raise validation_failed_error
end

def validate
validates_presence :name
validates_unique :name
Expand Down
20 changes: 20 additions & 0 deletions spec/unit/actions/organization_quotas_create_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,26 @@ module VCAP::CloudController
end
end

context 'when creating organization quotas concurrently' do
let(:name) { 'awesome' }
let(:message) { VCAP::CloudController::OrganizationQuotasCreateMessage.new(name:) }

it 'ensures one creation is successful and the other fails due to name conflict' do
# First request, should succeed
expect do
org_quotas_create.create(message)
end.not_to raise_error

# Mock the validation for the second request to simulate the race condition and trigger a unique constraint violation
allow_any_instance_of(QuotaDefinition).to receive(:validate).and_return(true)

# Second request, should fail with correct error
expect do
org_quotas_create.create(message)
end.to raise_error(OrganizationQuotasCreate::Error, "Organization Quota 'awesome' already exists.")
end
end

context 'when the org guid is invalid' do
let(:invalid_org_guid) { 'invalid_org_guid' }
let(:message_with_invalid_org_guid) do
Expand Down
Loading