58 lines
1.9 KiB
Ruby
58 lines
1.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Gitlab
|
|
module BackgroundMigration
|
|
# Remove duplicated service records with the same project and type.
|
|
# These were created in the past for unknown reasons, and should be blocked
|
|
# now by the uniqueness validation in the Service model.
|
|
class RemoveDuplicateServices
|
|
# See app/models/service
|
|
class Service < ActiveRecord::Base
|
|
include EachBatch
|
|
|
|
self.table_name = 'services'
|
|
self.inheritance_column = :_type_disabled
|
|
|
|
scope :project_ids_with_duplicates, -> do
|
|
select(:project_id)
|
|
.distinct
|
|
.where.not(project_id: nil)
|
|
.group(:project_id, :type)
|
|
.having('count(*) > 1')
|
|
end
|
|
|
|
scope :types_with_duplicates, -> (project_ids) do
|
|
select(:project_id, :type)
|
|
.where(project_id: project_ids)
|
|
.group(:project_id, :type)
|
|
.having('count(*) > 1')
|
|
end
|
|
end
|
|
|
|
def perform(*project_ids)
|
|
types_with_duplicates = Service.types_with_duplicates(project_ids).pluck(:project_id, :type)
|
|
|
|
types_with_duplicates.each do |project_id, type|
|
|
remove_duplicates(project_id, type)
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def remove_duplicates(project_id, type)
|
|
scope = Service.where(project_id: project_id, type: type)
|
|
|
|
# Build a subquery to determine which service record is actually in use,
|
|
# by querying for it without specifying an order.
|
|
#
|
|
# This should match the record returned by `Project#find_service`,
|
|
# and the `has_one` service associations on `Project`.
|
|
correct_service = scope.select(:id).limit(1)
|
|
|
|
# Delete all other services with the same `project_id` and `type`
|
|
duplicate_services = scope.where.not(id: correct_service)
|
|
duplicate_services.delete_all
|
|
end
|
|
end
|
|
end
|
|
end
|