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:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-03-16 21:18:33 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-03-16 21:18:33 +0300
commitf64a639bcfa1fc2bc89ca7db268f594306edfd7c (patch)
treea2c3c2ebcc3b45e596949db485d6ed18ffaacfa1 /lib/gitlab/graphql
parentbfbc3e0d6583ea1a91f627528bedc3d65ba4b10f (diff)
Add latest changes from gitlab-org/gitlab@13-10-stable-eev13.10.0-rc40
Diffstat (limited to 'lib/gitlab/graphql')
-rw-r--r--lib/gitlab/graphql/calls_gitaly.rb15
-rw-r--r--lib/gitlab/graphql/calls_gitaly/field_extension.rb87
-rw-r--r--lib/gitlab/graphql/calls_gitaly/instrumentation.rb40
-rw-r--r--lib/gitlab/graphql/docs/helper.rb53
-rw-r--r--lib/gitlab/graphql/docs/templates/default.md.haml87
-rw-r--r--lib/gitlab/graphql/extensions/externally_paginated_array_extension.rb2
-rw-r--r--lib/gitlab/graphql/pagination/keyset/connection.rb1
-rw-r--r--lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb47
-rw-r--r--lib/gitlab/graphql/pagination/keyset/last_items.rb38
-rw-r--r--lib/gitlab/graphql/pagination/keyset/order_info.rb7
-rw-r--r--lib/gitlab/graphql/present.rb23
-rw-r--r--lib/gitlab/graphql/present/field_extension.rb36
-rw-r--r--lib/gitlab/graphql/present/instrumentation.rb49
-rw-r--r--lib/gitlab/graphql/query_analyzers/logger_analyzer.rb4
14 files changed, 308 insertions, 181 deletions
diff --git a/lib/gitlab/graphql/calls_gitaly.rb b/lib/gitlab/graphql/calls_gitaly.rb
deleted file mode 100644
index 40cd74a34f2..00000000000
--- a/lib/gitlab/graphql/calls_gitaly.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Graphql
- # Wraps the field resolution to count Gitaly calls before and after.
- # Raises an error if the field calls Gitaly but hadn't declared such.
- module CallsGitaly
- extend ActiveSupport::Concern
-
- def self.use(schema_definition)
- schema_definition.instrument(:field, Gitlab::Graphql::CallsGitaly::Instrumentation.new, after_built_ins: true)
- end
- end
- end
-end
diff --git a/lib/gitlab/graphql/calls_gitaly/field_extension.rb b/lib/gitlab/graphql/calls_gitaly/field_extension.rb
new file mode 100644
index 00000000000..32530b47ce3
--- /dev/null
+++ b/lib/gitlab/graphql/calls_gitaly/field_extension.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ module CallsGitaly
+ # Check if any `calls_gitaly: true` declarations need to be added
+ #
+ # See BaseField: this extension is not applied if the field does not
+ # need it (i.e. it has a constant complexity or knows that it calls
+ # gitaly)
+ class FieldExtension < ::GraphQL::Schema::FieldExtension
+ include Laziness
+
+ def resolve(object:, arguments:, **rest)
+ yield(object, arguments, [current_gitaly_call_count, accounted_for])
+ end
+
+ def after_resolve(value:, memo:, **rest)
+ (value, count) = value_with_count(value, memo)
+ calls_gitaly_check(count)
+ accounted_for(count)
+
+ value
+ end
+
+ private
+
+ # Resolutions are not nested nicely (due to laziness), so we have to
+ # know not just how many calls were made before resolution started, but
+ # also how many were accounted for by fields with the correct settings
+ # in between.
+ #
+ # e.g. the following is not just plausible, but common:
+ #
+ # enter A.user (lazy)
+ # enter A.x
+ # leave A.x
+ # enter A.calls_gitaly
+ # leave A.calls_gitaly (accounts for 1 call)
+ # leave A.user
+ #
+ # In this circumstance we need to mark the calls made by A.calls_gitaly
+ # as accounted for, even though they were made after we yielded
+ # in A.user
+ def value_with_count(value, (previous_count, previous_accounted_for))
+ newly_accounted_for = accounted_for - previous_accounted_for
+ value = force(value)
+ count = [current_gitaly_call_count - (previous_count + newly_accounted_for), 0].max
+
+ [value, count]
+ end
+
+ def current_gitaly_call_count
+ Gitlab::GitalyClient.get_request_count || 0
+ end
+
+ def calls_gitaly_check(calls)
+ return if calls < 1 || field.may_call_gitaly?
+
+ error = RuntimeError.new(<<~ERROR)
+ #{field_name} unexpectedly calls Gitaly!
+
+ Please either specify a constant complexity or add `calls_gitaly: true`
+ to the field declaration
+ ERROR
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
+ end
+
+ def accounted_for(count = nil)
+ return 0 unless Gitlab::SafeRequestStore.active?
+
+ Gitlab::SafeRequestStore["graphql_gitaly_accounted_for"] ||= 0
+
+ if count.nil?
+ Gitlab::SafeRequestStore["graphql_gitaly_accounted_for"]
+ else
+ Gitlab::SafeRequestStore["graphql_gitaly_accounted_for"] += count
+ end
+ end
+
+ def field_name
+ "#{field.owner.graphql_name}.#{field.graphql_name}"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/calls_gitaly/instrumentation.rb b/lib/gitlab/graphql/calls_gitaly/instrumentation.rb
deleted file mode 100644
index 11d3c50e093..00000000000
--- a/lib/gitlab/graphql/calls_gitaly/instrumentation.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Graphql
- module CallsGitaly
- class Instrumentation
- # Check if any `calls_gitaly: true` declarations need to be added
- # Do nothing if a constant complexity was provided
- def instrument(_type, field)
- type_object = field.metadata[:type_class]
- return field unless type_object.respond_to?(:calls_gitaly?)
- return field if type_object.constant_complexity? || type_object.calls_gitaly?
-
- old_resolver_proc = field.resolve_proc
-
- gitaly_wrapped_resolve = -> (typed_object, args, ctx) do
- previous_gitaly_call_count = Gitlab::GitalyClient.get_request_count
- result = old_resolver_proc.call(typed_object, args, ctx)
- current_gitaly_call_count = Gitlab::GitalyClient.get_request_count
- calls_gitaly_check(type_object, current_gitaly_call_count - previous_gitaly_call_count)
- result
- end
-
- field.redefine do
- resolve(gitaly_wrapped_resolve)
- end
- end
-
- def calls_gitaly_check(type_object, calls)
- return if calls < 1
-
- # Will inform you if there needs to be `calls_gitaly: true` as a kwarg in the field declaration
- # if there is at least 1 Gitaly call involved with the field resolution.
- error = RuntimeError.new("Gitaly is called for field '#{type_object.name}' on #{type_object.owner.try(:name)} - please either specify a constant complexity or add `calls_gitaly: true` to the field declaration")
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/graphql/docs/helper.rb b/lib/gitlab/graphql/docs/helper.rb
index ad9e08e189c..e9ff85d9ca9 100644
--- a/lib/gitlab/graphql/docs/helper.rb
+++ b/lib/gitlab/graphql/docs/helper.rb
@@ -27,33 +27,36 @@ module Gitlab
MD
end
- def render_name_and_description(object)
- content = "### #{object[:name]}\n"
+ def render_name_and_description(object, level = 3)
+ content = []
+
+ content << "#{'#' * level} `#{object[:name]}`"
if object[:description].present?
- content += "\n#{object[:description]}.\n"
+ desc = object[:description].strip
+ desc += '.' unless desc.ends_with?('.')
+ content << desc
end
- content
+ content.join("\n\n")
end
def sorted_by_name(objects)
+ return [] unless objects.present?
+
objects.sort_by { |o| o[:name] }
end
def render_field(field)
- '| %s | %s | %s |' % [
- render_name(field),
- render_field_type(field[:type][:info]),
- render_description(field)
- ]
+ row(render_name(field), render_field_type(field[:type]), render_description(field))
end
def render_enum_value(value)
- '| %s | %s |' % [
- render_name(value),
- render_description(value)
- ]
+ row(render_name(value), render_description(value))
+ end
+
+ def row(*values)
+ "| #{values.join(' | ')} |"
end
def render_name(object)
@@ -70,27 +73,19 @@ module Gitlab
"**Deprecated:** #{object[:deprecation_reason]}"
end
- # Some fields types are arrays of other types and are displayed
- # on docs wrapped in square brackets, for example: [String!].
- # This makes GitLab docs renderer thinks they are links so here
- # we change them to be rendered as: String! => Array.
def render_field_type(type)
- array_type = type[/\[(.+)\]/, 1]
+ "[`#{type[:info]}`](##{type[:name].downcase})"
+ end
- if array_type
- "#{array_type} => Array"
- else
- type
- end
+ def render_return_type(query)
+ "Returns #{render_field_type(query[:type])}.\n"
end
# We are ignoring connections and built in types for now,
# they should be added when queries are generated.
def objects
object_types = graphql_object_types.select do |object_type|
- !object_type[:name]["Connection"] &&
- !object_type[:name]["Edge"] &&
- !object_type[:name]["__"]
+ !object_type[:name]["__"]
end
object_types.each do |type|
@@ -98,10 +93,14 @@ module Gitlab
end
end
+ def queries
+ graphql_operation_types.find { |type| type[:name] == 'Query' }.to_h.values_at(:fields, :connections).flatten
+ end
+
# We ignore the built-in enum types.
def enums
graphql_enum_types.select do |enum_type|
- !enum_type[:name].in?(%w(__DirectiveLocation __TypeKind))
+ !enum_type[:name].in?(%w[__DirectiveLocation __TypeKind])
end
end
end
diff --git a/lib/gitlab/graphql/docs/templates/default.md.haml b/lib/gitlab/graphql/docs/templates/default.md.haml
index 9dfb9b090a8..847f1777b08 100644
--- a/lib/gitlab/graphql/docs/templates/default.md.haml
+++ b/lib/gitlab/graphql/docs/templates/default.md.haml
@@ -14,13 +14,31 @@
WARNING:
Fields that are deprecated are marked with **{warning-solid}**.
- Items (fields, enums, etc) that have been removed according to our [deprecation process](../index.md#deprecation-process) can be found
+ Items (fields, enums, etc) that have been removed according to our [deprecation process](../index.md#deprecation-and-removal-process) can be found
in [Removed Items](../removed_items.md).
<!-- vale gitlab.Spelling = NO -->
\
:plain
+ ## `Query` type
+
+ The `Query` type contains the API's top-level entry points for all executable queries.
+\
+
+- sorted_by_name(queries).each do |query|
+ = render_name_and_description(query)
+ \
+ = render_return_type(query)
+ - unless query[:arguments].empty?
+ ~ "#### Arguments\n"
+ ~ "| Name | Type | Description |"
+ ~ "| ---- | ---- | ----------- |"
+ - sorted_by_name(query[:arguments]).each do |argument|
+ = render_field(argument)
+ \
+
+:plain
## Object types
Object types represent the resources that the GitLab GraphQL API can return.
@@ -36,6 +54,7 @@
- objects.each do |type|
- unless type[:fields].empty?
= render_name_and_description(type)
+ \
~ "| Field | Type | Description |"
~ "| ----- | ---- | ----------- |"
- sorted_by_name(type[:fields]).each do |field|
@@ -56,8 +75,74 @@
- enums.each do |enum|
- unless enum[:values].empty?
= render_name_and_description(enum)
+ \
~ "| Value | Description |"
~ "| ----- | ----------- |"
- sorted_by_name(enum[:values]).each do |value|
= render_enum_value(value)
\
+
+:plain
+ ## Scalar types
+
+ Scalar values are atomic values, and do not have fields of their own.
+ Basic scalars include strings, boolean values, and numbers. This schema also
+ defines various custom scalar values, such as types for times and dates.
+
+ This schema includes custom scalar types for identifiers, with a specific type for
+ each kind of object.
+
+ For more information, read about [Scalar Types](https://graphql.org/learn/schema/#scalar-types) on `graphql.org`.
+\
+
+- graphql_scalar_types.each do |type|
+ = render_name_and_description(type)
+ \
+
+:plain
+ ## Abstract types
+
+ Abstract types (unions and interfaces) are ways the schema can represent
+ values that may be one of several concrete types.
+
+ - A [`Union`](https://graphql.org/learn/schema/#union-types) is a set of possible types.
+ The types might not have any fields in common.
+ - An [`Interface`](https://graphql.org/learn/schema/#interfaces) is a defined set of fields.
+ Types may `implement` an interface, which
+ guarantees that they have all the fields in the set. A type may implement more than
+ one interface.
+
+ See the [GraphQL documentation](https://graphql.org/learn/) for more information on using
+ abstract types.
+\
+
+:plain
+ ### Unions
+\
+
+- graphql_union_types.each do |type|
+ = render_name_and_description(type, 4)
+ \
+ One of:
+ \
+ - type[:possible_types].each do |type_name|
+ ~ "- [`#{type_name}`](##{type_name.downcase})"
+ \
+
+:plain
+ ### Interfaces
+\
+
+- graphql_interface_types.each do |type|
+ = render_name_and_description(type, 4)
+ \
+ Implementations:
+ \
+ - type[:implemented_by].each do |type_name|
+ ~ "- [`#{type_name}`](##{type_name.downcase})"
+ \
+ ~ "| Field | Type | Description |"
+ ~ "| ----- | ---- | ----------- |"
+ - sorted_by_name(type[:fields] + type[:connections]).each do |field|
+ = render_field(field)
+ \
diff --git a/lib/gitlab/graphql/extensions/externally_paginated_array_extension.rb b/lib/gitlab/graphql/extensions/externally_paginated_array_extension.rb
index 1adedb500e6..f787e7be94a 100644
--- a/lib/gitlab/graphql/extensions/externally_paginated_array_extension.rb
+++ b/lib/gitlab/graphql/extensions/externally_paginated_array_extension.rb
@@ -4,7 +4,7 @@ module Gitlab
module Extensions
class ExternallyPaginatedArrayExtension < GraphQL::Schema::Field::ConnectionExtension
def resolve(object:, arguments:, context:)
- yield(object, arguments)
+ yield(object, arguments, arguments)
end
end
end
diff --git a/lib/gitlab/graphql/pagination/keyset/connection.rb b/lib/gitlab/graphql/pagination/keyset/connection.rb
index f95c91c5706..e525996ec10 100644
--- a/lib/gitlab/graphql/pagination/keyset/connection.rb
+++ b/lib/gitlab/graphql/pagination/keyset/connection.rb
@@ -33,6 +33,7 @@ module Gitlab
include Gitlab::Utils::StrongMemoize
include ::Gitlab::Graphql::ConnectionCollectionMethods
prepend ::Gitlab::Graphql::ConnectionRedaction
+ prepend GenericKeysetPagination
# rubocop: disable Naming/PredicateName
# https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo.Fields
diff --git a/lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb b/lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb
new file mode 100644
index 00000000000..318c6e1734f
--- /dev/null
+++ b/lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ module Pagination
+ module Keyset
+ # Use the generic keyset implementation if the given ActiveRecord scope supports it.
+ # Note: this module is temporary, at some point it will be merged with Keyset::Connection
+ module GenericKeysetPagination
+ extend ActiveSupport::Concern
+
+ def ordered_items
+ return super unless Gitlab::Pagination::Keyset::Order.keyset_aware?(items)
+
+ items
+ end
+
+ def cursor_for(node)
+ return super unless Gitlab::Pagination::Keyset::Order.keyset_aware?(items)
+
+ order = Gitlab::Pagination::Keyset::Order.extract_keyset_order_object(items)
+ encode(order.cursor_attributes_for_node(node).to_json)
+ end
+
+ def slice_nodes(sliced, encoded_cursor, before_or_after)
+ return super unless Gitlab::Pagination::Keyset::Order.keyset_aware?(sliced)
+
+ order = Gitlab::Pagination::Keyset::Order.extract_keyset_order_object(sliced)
+ order = order.reversed_order if before_or_after == :before
+
+ decoded_cursor = ordering_from_encoded_json(encoded_cursor)
+ order.apply_cursor_conditions(sliced, decoded_cursor)
+ end
+
+ def sliced_nodes
+ return super unless Gitlab::Pagination::Keyset::Order.keyset_aware?(items)
+
+ sliced = ordered_items
+ sliced = slice_nodes(sliced, before, :before) if before.present?
+ sliced = slice_nodes(sliced, after, :after) if after.present?
+ sliced
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/pagination/keyset/last_items.rb b/lib/gitlab/graphql/pagination/keyset/last_items.rb
index 45bf15236c1..960567a6fbc 100644
--- a/lib/gitlab/graphql/pagination/keyset/last_items.rb
+++ b/lib/gitlab/graphql/pagination/keyset/last_items.rb
@@ -10,46 +10,14 @@ module Gitlab
class LastItems
# rubocop: disable CodeReuse/ActiveRecord
def self.take_items(scope, count)
- if custom_order = lookup_custom_reverse_order(scope.order_values)
- items = scope.reorder(*custom_order).first(count) # returns a single record when count is nil
+ if Gitlab::Pagination::Keyset::Order.keyset_aware?(scope)
+ order = Gitlab::Pagination::Keyset::Order.extract_keyset_order_object(scope)
+ items = scope.reorder(order.reversed_order).first(count)
items.is_a?(Array) ? items.reverse : items
else
scope.last(count)
end
end
- # rubocop: enable CodeReuse/ActiveRecord
-
- # Detect special ordering and provide the reversed order
- def self.lookup_custom_reverse_order(order_values)
- if ordering_by_merged_at_and_mr_id_desc?(order_values)
- [
- Gitlab::Database.nulls_first_order('merge_request_metrics.merged_at', 'ASC'), # reversing the order
- MergeRequest.arel_table[:id].asc
- ]
- elsif ordering_by_merged_at_and_mr_id_asc?(order_values)
- [
- Gitlab::Database.nulls_first_order('merge_request_metrics.merged_at', 'DESC'),
- MergeRequest.arel_table[:id].asc
- ]
- end
- end
-
- def self.ordering_by_merged_at_and_mr_id_desc?(order_values)
- order_values.size == 2 &&
- order_values.first.to_s == Gitlab::Database.nulls_last_order('merge_request_metrics.merged_at', 'DESC') &&
- order_values.last.is_a?(Arel::Nodes::Descending) &&
- order_values.last.to_sql == MergeRequest.arel_table[:id].desc.to_sql
- end
-
- def self.ordering_by_merged_at_and_mr_id_asc?(order_values)
- order_values.size == 2 &&
- order_values.first.to_s == Gitlab::Database.nulls_last_order('merge_request_metrics.merged_at', 'ASC') &&
- order_values.last.is_a?(Arel::Nodes::Descending) &&
- order_values.last.to_sql == MergeRequest.arel_table[:id].desc.to_sql
- end
-
- private_class_method :ordering_by_merged_at_and_mr_id_desc?
- private_class_method :ordering_by_merged_at_and_mr_id_asc?
end
end
end
diff --git a/lib/gitlab/graphql/pagination/keyset/order_info.rb b/lib/gitlab/graphql/pagination/keyset/order_info.rb
index d37264c1343..0494329bfd9 100644
--- a/lib/gitlab/graphql/pagination/keyset/order_info.rb
+++ b/lib/gitlab/graphql/pagination/keyset/order_info.rb
@@ -92,8 +92,6 @@ module Gitlab
def extract_attribute_values(order_value)
if ordering_by_lower?(order_value)
[order_value.expr.expressions[0].name.to_s, order_value.direction, order_value.expr]
- elsif ordering_by_similarity?(order_value)
- ['similarity', order_value.direction, order_value.expr]
elsif ordering_by_case?(order_value)
['case_order_value', order_value.direction, order_value.expr]
elsif ordering_by_array_position?(order_value)
@@ -113,11 +111,6 @@ module Gitlab
order_value.expr.is_a?(Arel::Nodes::NamedFunction) && order_value.expr&.name&.downcase == 'array_position'
end
- # determine if ordering using SIMILARITY scoring based on Gitlab::Database::SimilarityScore
- def ordering_by_similarity?(order_value)
- Gitlab::Database::SimilarityScore.order_by_similarity?(order_value)
- end
-
# determine if ordering using CASE
def ordering_by_case?(order_value)
order_value.expr.is_a?(Arel::Nodes::Case)
diff --git a/lib/gitlab/graphql/present.rb b/lib/gitlab/graphql/present.rb
index 6d86d632ab4..fdaf075eb25 100644
--- a/lib/gitlab/graphql/present.rb
+++ b/lib/gitlab/graphql/present.rb
@@ -12,11 +12,30 @@ module Gitlab
def self.presenter_class
@presenter_class
end
+
+ def self.present(object, attrs)
+ klass = @presenter_class
+ return object if !klass || object.is_a?(klass)
+
+ @presenter_class.new(object, **attrs)
+ end
+ end
+
+ def unpresented
+ unwrapped || object
end
- def self.use(schema_definition)
- schema_definition.instrument(:field, ::Gitlab::Graphql::Present::Instrumentation.new)
+ def present(object_type, attrs)
+ return unless object_type.respond_to?(:present)
+
+ self.unwrapped ||= object
+ # @object belongs to Schema::Object, which does not expose a writer.
+ @object = object_type.present(unwrapped, attrs) # rubocop: disable Gitlab/ModuleWithInstanceVariables
end
+
+ private
+
+ attr_accessor :unwrapped
end
end
end
diff --git a/lib/gitlab/graphql/present/field_extension.rb b/lib/gitlab/graphql/present/field_extension.rb
new file mode 100644
index 00000000000..2e211b70d35
--- /dev/null
+++ b/lib/gitlab/graphql/present/field_extension.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ module Present
+ class FieldExtension < ::GraphQL::Schema::FieldExtension
+ SAFE_CONTEXT_KEYS = %i[current_user].freeze
+
+ def resolve(object:, arguments:, context:)
+ attrs = safe_context_values(context)
+
+ # We need to handle the object being either a Schema::Object or an
+ # inner Schema::Object#object. This depends on whether the field
+ # has a @resolver_proc or not.
+ if object.is_a?(::Types::BaseObject)
+ object.present(field.owner, attrs)
+ yield(object, arguments)
+ else
+ # This is the legacy code-path, hit if the field has a @resolver_proc
+ # TODO: remove this when resolve procs are removed from the
+ # graphql-ruby library, and all field instrumentation is removed.
+ # See: https://github.com/rmosolgo/graphql-ruby/issues/3385
+ presented = field.owner.try(:present, object, attrs) || object
+ yield(presented, arguments)
+ end
+ end
+
+ private
+
+ def safe_context_values(context)
+ context.to_h.slice(*SAFE_CONTEXT_KEYS)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/present/instrumentation.rb b/lib/gitlab/graphql/present/instrumentation.rb
deleted file mode 100644
index b8535575da5..00000000000
--- a/lib/gitlab/graphql/present/instrumentation.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Graphql
- module Present
- class Instrumentation
- SAFE_CONTEXT_KEYS = %i[current_user].freeze
-
- def instrument(type, field)
- return field unless field.metadata[:type_class]
-
- presented_in = field.metadata[:type_class].owner
- return field unless presented_in.respond_to?(:presenter_class)
- return field unless presented_in.presenter_class
-
- old_resolver = field.resolve_proc
-
- resolve_with_presenter = -> (presented_type, args, context) do
- # We need to wrap the original presentation type into a type that
- # uses the presenter as an object.
- object = presented_type.object
-
- if object.is_a?(presented_in.presenter_class)
- next old_resolver.call(presented_type, args, context)
- end
-
- attrs = safe_context_values(context)
- presenter = presented_in.presenter_class.new(object, **attrs)
-
- # we have to use the new `authorized_new` method, as `new` is protected
- wrapped = presented_type.class.authorized_new(presenter, context)
-
- old_resolver.call(wrapped, args, context)
- end
-
- field.redefine do
- resolve(resolve_with_presenter)
- end
- end
-
- private
-
- def safe_context_values(context)
- context.to_h.slice(*SAFE_CONTEXT_KEYS)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/graphql/query_analyzers/logger_analyzer.rb b/lib/gitlab/graphql/query_analyzers/logger_analyzer.rb
index 0665ea8b6c9..8acd27869a9 100644
--- a/lib/gitlab/graphql/query_analyzers/logger_analyzer.rb
+++ b/lib/gitlab/graphql/query_analyzers/logger_analyzer.rb
@@ -9,10 +9,6 @@ module Gitlab
FIELD_USAGE_ANALYZER = GraphQL::Analysis::FieldUsage.new { |query, used_fields, used_deprecated_fields| [used_fields, used_deprecated_fields] }
ALL_ANALYZERS = [COMPLEXITY_ANALYZER, DEPTH_ANALYZER, FIELD_USAGE_ANALYZER].freeze
- def analyze?(query)
- Feature.enabled?(:graphql_logging, default_enabled: true)
- end
-
def initial_value(query)
variables = process_variables(query.provided_variables)
default_initial_values(query).merge({