Skip to content

Commit

Permalink
Add unique index to svc_inst_op on svc_inst_id
Browse files Browse the repository at this point in the history
* Add unique index on column service_instance_id to prevent double entries for the same
  service_instance
* Remove duplicate service_instance_id entries based on max(updated_at) (=keep the newest entry)
  to prepare for adding a uniqueness constraint
* Drop foreign_key constraint which references service_instance_id (needed for mysql) and
  old index before creating the unique index

Compared to service bindings, service keys and route bindings there is a UNIQUE index
defined for the "resource_id" field; for service instances the UNIQUE keyword is missing.
  • Loading branch information
kathap committed Aug 29, 2022
1 parent 2ab201a commit be9fb5e
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Sequel.migration do
up do
# Remove duplicate service_instance_operations.service_instance_id to prepare for adding a uniqueness constraint
max_updated_at_group = self[:service_instance_operations].
select(Sequel.function(:max, :updated_at)).
group_by(:service_instance_id).
having { count.function.* >= 1 }
service_instance_id_group = self[:service_instance_operations].
select(:service_instance_id).
group_by(:service_instance_id).
having { count.function.* >= 1 }
self[:service_instance_operations].exclude(id: self[:service_instance_operations].select(:id).
where { Sequel.&(Sequel.|({ service_instance_id: service_instance_id_group }, { service_instance_id: nil }),
{ updated_at: max_updated_at_group })
}).each do |row|
self[:service_instance_operations].where(id: row[:id]).delete
end
# for mysql the foreign_key constraint which references service_instance_id has to be removed before you can
# delete the old index from service_instance_id
alter_table :service_instance_operations do
drop_constraint :fk_svc_inst_op_svc_instance_id, type: :foreign_key
drop_index :service_instance_id, name: :svc_instance_id_index
add_index :service_instance_id, name: :svc_inst_op_svc_instance_id_unique_index, unique: true
add_foreign_key [:service_instance_id], :service_instances, key: :id, name: :fk_svc_inst_op_svc_instance_id, on_delete: :cascade
end
end
down do
alter_table :service_instance_operations do
drop_constraint :fk_svc_inst_op_svc_instance_id, type: :foreign_key
drop_index :service_instance_id, name: :svc_inst_op_svc_instance_id_unique_index
add_index :service_instance_id, name: :svc_instance_id_index
add_foreign_key [:service_instance_id], :service_instances, key: :id, name: :fk_svc_inst_op_svc_instance_id
end
end
end
32 changes: 32 additions & 0 deletions spec/unit/models/services/service_instance_operation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,37 @@ module VCAP::CloudController
expect(operation.state).to eq 'finished'
end
end

describe 'when two are created with the same id' do
describe 'when a ServiceInstanceOperation exists' do
let(:service_instance_attrs) do
{
name: 'bommel_instance',
space: VCAP::CloudController::Space.make
}
end

let(:service_instance) { ServiceInstance.create(service_instance_attrs) }
let(:operation_attributes2) do
{
service_instance_id: service_instance.id,
state: 'in progress',
description: '50% all the time',
type: 'create',
proposed_changes: {
name: 'pizza',
service_plan_guid: '1800-pizza',
},
}
end
before { ServiceInstanceOperation.create(operation_attributes2) }

it 'raises an exception when creating another ServiceInstanceOperation' do
expect {
ServiceInstanceOperation.create(operation_attributes2)
}.to raise_error(Sequel::UniqueConstraintViolation)
end
end
end
end
end

0 comments on commit be9fb5e

Please sign in to comment.