summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Provaznik <jprovaznik@gitlab.com>2019-05-06 13:43:02 +0200
committerJan Provaznik <jprovaznik@gitlab.com>2019-05-06 19:28:07 +0200
commitdebad672bf699e12f0efb5ed50dbf408fda94b3d (patch)
tree14300c954cddfd048f102aac55140afba7f76291
parente3a846d6fa68d2e9aab118b40bce326604a5d250 (diff)
downloadgitlab-ce-graphql-resolvers-complexity.tar.gz
Minor fixes and improvementsgraphql-resolvers-complexity
* added comments * added a test for pipelines
-rw-r--r--app/graphql/resolvers/base_resolver.rb7
-rw-r--r--app/graphql/resolvers/concerns/resolves_pipelines.rb2
-rw-r--r--app/graphql/types/base_field.rb13
-rw-r--r--spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb8
4 files changed, 25 insertions, 5 deletions
diff --git a/app/graphql/resolvers/base_resolver.rb b/app/graphql/resolvers/base_resolver.rb
index b7502eb97c5..31850c2cadb 100644
--- a/app/graphql/resolvers/base_resolver.rb
+++ b/app/graphql/resolvers/base_resolver.rb
@@ -19,6 +19,13 @@ module Resolvers
end
def self.complexity_multiplier(args)
+ # When fetching many items, additional complexity is added to the field
+ # depending on how many items is fetched. For each item we add 1% of the
+ # original complexity - this means that loading 100 items (our default
+ # maxp_age_size limit) doubles the original complexity.
+ #
+ # Complexity is not increased when searching by specific ID(s), because
+ # complexity difference is minimal in this case.
[args[:iid], args[:iids]].any? ? 0 : 0.01
end
end
diff --git a/app/graphql/resolvers/concerns/resolves_pipelines.rb b/app/graphql/resolvers/concerns/resolves_pipelines.rb
index e611a6fc571..a166211fc18 100644
--- a/app/graphql/resolvers/concerns/resolves_pipelines.rb
+++ b/app/graphql/resolvers/concerns/resolves_pipelines.rb
@@ -20,7 +20,7 @@ module ResolvesPipelines
end
class_methods do
- def complexity(args)
+ def resolver_complexity(args)
complexity = super
complexity += 2 if args[:sha]
complexity += 2 if args[:ref]
diff --git a/app/graphql/types/base_field.rb b/app/graphql/types/base_field.rb
index 732ecc92da4..15331129134 100644
--- a/app/graphql/types/base_field.rb
+++ b/app/graphql/types/base_field.rb
@@ -7,22 +7,27 @@ module Types
DEFAULT_COMPLEXITY = 1
def initialize(*args, **kwargs, &block)
- kwargs[:complexity] ||= set_complexity(kwargs[:resolver_class])
+ kwargs[:complexity] ||= field_complexity(kwargs[:resolver_class])
super(*args, **kwargs, &block)
end
private
- def set_complexity(resolver_class)
+ def field_complexity(resolver_class)
if resolver_class
- resolver_complexity
+ field_resolver_complexity
else
DEFAULT_COMPLEXITY
end
end
- def resolver_complexity
+ def field_resolver_complexity
+ # Complexity can be either integer or proc. If proc is used then it's
+ # called when computing a query complexity and context and query
+ # arguments are available for computing complexity. For resolvers we use
+ # proc because we set complexity depending on arguments and number of
+ # items which can be loaded.
proc do |ctx, args, child_complexity|
page_size = @max_page_size || ctx.schema.default_max_page_size
limit_value = [args[:first], args[:last], page_size].compact.min
diff --git a/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb b/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb
index ea7159eacf9..3140af27af5 100644
--- a/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb
+++ b/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb
@@ -46,6 +46,14 @@ describe ResolvesPipelines do
expect(resolve_pipelines({}, {})).to be_empty
end
+ it 'increases field complexity based on arguments' do
+ field = Types::BaseField.new(name: 'test', type: GraphQL::STRING_TYPE, resolver_class: resolver, null: false, max_page_size: 1)
+
+ expect(field.to_graphql.complexity.call({}, {}, 1)).to eq 2
+ expect(field.to_graphql.complexity.call({}, { sha: 'foo' }, 1)).to eq 4
+ expect(field.to_graphql.complexity.call({}, { sha: 'ref' }, 1)).to eq 4
+ end
+
def resolve_pipelines(args = {}, context = { current_user: current_user })
resolve(resolver, obj: project, args: args, ctx: context)
end