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/graphql/resolvers/concerns')
-rw-r--r--app/graphql/resolvers/concerns/looks_ahead.rb52
-rw-r--r--app/graphql/resolvers/concerns/resolves_merge_requests.rb67
-rw-r--r--app/graphql/resolvers/concerns/resolves_project.rb15
3 files changed, 134 insertions, 0 deletions
diff --git a/app/graphql/resolvers/concerns/looks_ahead.rb b/app/graphql/resolvers/concerns/looks_ahead.rb
new file mode 100644
index 00000000000..becc6debd33
--- /dev/null
+++ b/app/graphql/resolvers/concerns/looks_ahead.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module LooksAhead
+ extend ActiveSupport::Concern
+
+ FEATURE_FLAG = :graphql_lookahead_support
+
+ included do
+ attr_accessor :lookahead
+ end
+
+ def resolve(**args)
+ self.lookahead = args.delete(:lookahead)
+
+ resolve_with_lookahead(**args)
+ end
+
+ def apply_lookahead(query)
+ return query unless Feature.enabled?(FEATURE_FLAG)
+
+ selection = node_selection
+
+ includes = preloads.each.flat_map do |name, requirements|
+ selection&.selects?(name) ? requirements : []
+ end
+ preloads = (unconditional_includes + includes).uniq
+
+ return query if preloads.empty?
+
+ query.preload(*preloads) # rubocop: disable CodeReuse/ActiveRecord
+ end
+
+ private
+
+ def unconditional_includes
+ []
+ end
+
+ def preloads
+ {}
+ end
+
+ def node_selection
+ return unless lookahead
+
+ if lookahead.selects?(:nodes)
+ lookahead.selection(:nodes)
+ elsif lookahead.selects?(:edges)
+ lookahead.selection(:edges).selection(:nodes)
+ end
+ end
+end
diff --git a/app/graphql/resolvers/concerns/resolves_merge_requests.rb b/app/graphql/resolvers/concerns/resolves_merge_requests.rb
new file mode 100644
index 00000000000..a2140728a27
--- /dev/null
+++ b/app/graphql/resolvers/concerns/resolves_merge_requests.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+# Mixin for resolving merge requests. All arguments must be in forms
+# that `MergeRequestsFinder` can handle, so you may need to use aliasing.
+module ResolvesMergeRequests
+ extend ActiveSupport::Concern
+ include LooksAhead
+
+ included do
+ type Types::MergeRequestType, null: true
+ end
+
+ def resolve_with_lookahead(**args)
+ args[:iids] = Array.wrap(args[:iids]) if args[:iids]
+ args.compact!
+
+ if project && args.keys == [:iids]
+ batch_load_merge_requests(args[:iids])
+ else
+ args[:project_id] ||= project
+
+ apply_lookahead(MergeRequestsFinder.new(current_user, args).execute)
+ end.then(&(single? ? :first : :itself))
+ end
+
+ def ready?(**args)
+ return early_return if no_results_possible?(args)
+
+ super
+ end
+
+ def early_return
+ [false, single? ? nil : MergeRequest.none]
+ end
+
+ private
+
+ def batch_load_merge_requests(iids)
+ iids.map { |iid| batch_load(iid) }.select(&:itself) # .compact doesn't work on BatchLoader
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def batch_load(iid)
+ BatchLoader::GraphQL.for(iid.to_s).batch(key: project) do |iids, loader, args|
+ query = args[:key].merge_requests.where(iid: iids)
+
+ apply_lookahead(query).each do |mr|
+ loader.call(mr.iid.to_s, mr)
+ end
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def unconditional_includes
+ [:target_project]
+ end
+
+ def preloads
+ {
+ assignees: [:assignees],
+ labels: [:labels],
+ author: [:author],
+ milestone: [:milestone],
+ head_pipeline: [:merge_request_diff, { head_pipeline: [:merge_request] }]
+ }
+ end
+end
diff --git a/app/graphql/resolvers/concerns/resolves_project.rb b/app/graphql/resolvers/concerns/resolves_project.rb
new file mode 100644
index 00000000000..3c5ce3dab01
--- /dev/null
+++ b/app/graphql/resolvers/concerns/resolves_project.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module ResolvesProject
+ def resolve_project(full_path: nil, project_id: nil)
+ unless full_path.present? ^ project_id.present?
+ raise ::Gitlab::Graphql::Errors::ArgumentError, 'Incompatible arguments: projectId, projectPath.'
+ end
+
+ if full_path.present?
+ ::Gitlab::Graphql::Loaders::FullPathModelLoader.new(Project, full_path).find
+ else
+ ::GitlabSchema.object_from_id(project_id, expected_type: Project)
+ end
+ end
+end