diff options
author | Jan Provaznik <jprovaznik@gitlab.com> | 2019-05-06 13:43:02 +0200 |
---|---|---|
committer | Jan Provaznik <jprovaznik@gitlab.com> | 2019-05-06 19:28:07 +0200 |
commit | debad672bf699e12f0efb5ed50dbf408fda94b3d (patch) | |
tree | 14300c954cddfd048f102aac55140afba7f76291 | |
parent | e3a846d6fa68d2e9aab118b40bce326604a5d250 (diff) | |
download | gitlab-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.rb | 7 | ||||
-rw-r--r-- | app/graphql/resolvers/concerns/resolves_pipelines.rb | 2 | ||||
-rw-r--r-- | app/graphql/types/base_field.rb | 13 | ||||
-rw-r--r-- | spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb | 8 |
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 |