gitlab-org--gitlab-foss/app/services/packages/create_dependency_service.rb

81 lines
2.7 KiB
Ruby

# frozen_string_literal: true
module Packages
# rubocop: disable Gitlab/BulkInsert
class CreateDependencyService < BaseService
attr_reader :package, :dependencies
def initialize(package, dependencies)
@package = package
@dependencies = dependencies
end
def execute
Packages::DependencyLink.dependency_types.each_key do |type|
create_dependency(type)
end
end
private
def create_dependency(type)
return unless dependencies[type].is_a?(Hash)
names_and_version_patterns = dependencies[type]
existing_ids, existing_names = find_existing_ids_and_names(names_and_version_patterns)
dependencies_to_insert = names_and_version_patterns
if existing_names.any?
dependencies_to_insert = names_and_version_patterns.reject { |k, _| k.in?(existing_names) }
end
ApplicationRecord.transaction do
inserted_ids = bulk_insert_package_dependencies(dependencies_to_insert)
bulk_insert_package_dependency_links(type, (existing_ids + inserted_ids))
end
end
def find_existing_ids_and_names(names_and_version_patterns)
ids_and_names = Packages::Dependency.for_package_names_and_version_patterns(names_and_version_patterns)
.pluck_ids_and_names
ids = ids_and_names.map(&:first) || []
names = ids_and_names.map(&:second) || []
[ids, names]
end
def bulk_insert_package_dependencies(names_and_version_patterns)
return [] if names_and_version_patterns.empty?
rows = names_and_version_patterns.map do |name, version_pattern|
{
name: name,
version_pattern: version_pattern
}
end
ids = ApplicationRecord.legacy_bulk_insert(Packages::Dependency.table_name, rows, return_ids: true, on_conflict: :do_nothing)
return ids if ids.size == names_and_version_patterns.size
Packages::Dependency.uncached do
# The bulk_insert statement above do not dirty the query cache. To make
# sure that the results are fresh from the database and not from a stalled
# and potentially wrong cache, this query has to be done with the query
# chache disabled.
Packages::Dependency.ids_for_package_names_and_version_patterns(names_and_version_patterns)
end
end
def bulk_insert_package_dependency_links(type, dependency_ids)
rows = dependency_ids.map do |dependency_id|
{
package_id: package.id,
dependency_id: dependency_id,
dependency_type: Packages::DependencyLink.dependency_types[type.to_s]
}
end
ApplicationRecord.legacy_bulk_insert(Packages::DependencyLink.table_name, rows)
end
end
# rubocop: enable Gitlab/BulkInsert
end