diff --git a/app/models/services/service_instance.rb b/app/models/services/service_instance.rb index 259c6f620f8..a7162cfeb18 100644 --- a/app/models/services/service_instance.rb +++ b/app/models/services/service_instance.rb @@ -110,6 +110,15 @@ def name_clashes end end + def around_save + yield + rescue Sequel::UniqueConstraintViolation => e + raise e unless e.message.include?('si_space_id_name_index') + + errors.add(:name, :unique) + raise validation_failed_error + end + def validate validates_presence :name validates_presence :space diff --git a/spec/unit/actions/v3/service_instance_create_managed_spec.rb b/spec/unit/actions/v3/service_instance_create_managed_spec.rb index 9cf64cc76a2..4566528a268 100644 --- a/spec/unit/actions/v3/service_instance_create_managed_spec.rb +++ b/spec/unit/actions/v3/service_instance_create_managed_spec.rb @@ -214,6 +214,23 @@ module V3 end end + context 'parallel creation of managed service instances' do + it 'ensures one creation is successful and the other fails due to name conflict' do + # First request, should succeed + expect do + action.precursor(message:, service_plan:) + 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(ManagedServiceInstance).to receive(:validate).and_return(true) + + # Second request, should fail with correct error message + expect do + action.precursor(message:, service_plan:) + end.to raise_error(ServiceInstanceCreateManaged::InvalidManagedServiceInstance, 'The service instance name is taken: si-test-name.') + end + end + context 'quotas' do context 'when service instance limit has been reached for the space' do before do