Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/services/packages/create_dependency_service.rb')
-rw-r--r--app/services/packages/create_dependency_service.rb82
1 files changed, 82 insertions, 0 deletions
diff --git a/app/services/packages/create_dependency_service.rb b/app/services/packages/create_dependency_service.rb
new file mode 100644
index 00000000000..2999885d55d
--- /dev/null
+++ b/app/services/packages/create_dependency_service.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+module Packages
+ 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
+
+ ActiveRecord::Base.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 = database.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
+
+ database.bulk_insert(Packages::DependencyLink.table_name, rows)
+ end
+
+ def database
+ ::Gitlab::Database
+ end
+ end
+end