Commit 5fa4c7a6 authored by Jan Provaznik's avatar Jan Provaznik

Merge branch '262096-use-lookahead-to-preload-queries-for-requirementtype' into 'master'

GraphQL - Use Lookahead to preload tests reports in Requirements Management

See merge request gitlab-org/gitlab!45195
parents cebfe834 ac73a696
...@@ -57,6 +57,7 @@ module EE ...@@ -57,6 +57,7 @@ module EE
field :requirements, ::Types::RequirementsManagement::RequirementType.connection_type, null: true, field :requirements, ::Types::RequirementsManagement::RequirementType.connection_type, null: true,
description: 'Find requirements', description: 'Find requirements',
extras: [:lookahead],
resolver: ::Resolvers::RequirementsManagement::RequirementsResolver resolver: ::Resolvers::RequirementsManagement::RequirementsResolver
field :requirement_states_count, ::Types::RequirementsManagement::RequirementStatesCountType, null: true, field :requirement_states_count, ::Types::RequirementsManagement::RequirementStatesCountType, null: true,
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
module Resolvers module Resolvers
module RequirementsManagement module RequirementsManagement
class RequirementsResolver < BaseResolver class RequirementsResolver < BaseResolver
include LooksAhead
argument :iid, GraphQL::ID_TYPE, argument :iid, GraphQL::ID_TYPE,
required: false, required: false,
description: 'IID of the requirement, e.g., "1"' description: 'IID of the requirement, e.g., "1"'
...@@ -29,7 +31,7 @@ module Resolvers ...@@ -29,7 +31,7 @@ module Resolvers
type Types::RequirementsManagement::RequirementType, null: true type Types::RequirementsManagement::RequirementType, null: true
def resolve(**args) def resolve_with_lookahead(**args)
# The project could have been loaded in batch by `BatchLoader`. # The project could have been loaded in batch by `BatchLoader`.
# At this point we need the `id` of the project to query for issues, so # At this point we need the `id` of the project to query for issues, so
# make sure it's loaded and not `nil` before continuing. # make sure it's loaded and not `nil` before continuing.
...@@ -39,6 +41,19 @@ module Resolvers ...@@ -39,6 +41,19 @@ module Resolvers
args[:project_id] = project.id args[:project_id] = project.id
args[:iids] ||= [args[:iid]].compact args[:iids] ||= [args[:iid]].compact
apply_lookahead(find_requirements(args))
end
private
def preloads
{
last_test_report_manually_created: [:test_reports],
last_test_report_state: [:test_reports, { test_reports: [:build] }]
}
end
def find_requirements(args)
::RequirementsManagement::RequirementsFinder.new(context[:current_user], args).execute ::RequirementsManagement::RequirementsFinder.new(context[:current_user], args).execute
end end
end end
......
...@@ -27,14 +27,13 @@ module Types ...@@ -27,14 +27,13 @@ module Types
field :state, RequirementsManagement::RequirementStateEnum, null: false, field :state, RequirementsManagement::RequirementStateEnum, null: false,
description: 'State of the requirement' description: 'State of the requirement'
field :last_test_report_state, RequirementsManagement::TestReportStateEnum, null: true, complexity: 5, field :last_test_report_state, RequirementsManagement::TestReportStateEnum, null: true,
description: 'Latest requirement test report state' description: 'Latest requirement test report state'
field :last_test_report_manually_created, field :last_test_report_manually_created,
GraphQL::BOOLEAN_TYPE, GraphQL::BOOLEAN_TYPE,
method: :last_test_report_manually_created?, method: :last_test_report_manually_created?,
null: true, null: true,
complexity: 5,
description: 'Indicates if latest test report was created by user' description: 'Indicates if latest test report was created by user'
field :project, ProjectType, null: false, field :project, ProjectType, null: false,
......
---
title: Use Lookahead to preload tests reports when querying Requirements with GraphQL
merge_request: 45195
author:
type: performance
...@@ -63,6 +63,30 @@ RSpec.describe 'getting a requirement list for a project' do ...@@ -63,6 +63,30 @@ RSpec.describe 'getting a requirement list for a project' do
end end
end end
context 'query performance with test reports' do
let_it_be(:test_report) { create(:test_report, requirement: requirement, state: "passed") }
let(:fields) do
<<~QUERY
edges {
node {
lastTestReportState
lastTestReportManuallyCreated
}
}
QUERY
end
it 'avoids N+1 queries' do
control = ActiveRecord::QueryRecorder.new { post_graphql(query, current_user: current_user) }
create_list(:requirement, 3, project: project) do |requirement|
create(:test_report, requirement: requirement, state: "passed")
end
expect { post_graphql(query, current_user: current_user) }.not_to exceed_query_limit(control)
end
end
describe 'filtering' do describe 'filtering' do
let_it_be(:filter_project) { create(:project, :public) } let_it_be(:filter_project) { create(:project, :public) }
let_it_be(:other_project) { create(:project, :public) } let_it_be(:other_project) { create(:project, :public) }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment