From 06d4f07a041a70fe9462bcae47b1b191908347ab Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Tue, 26 Dec 2017 17:16:43 -0200 Subject: [PATCH] Improve filtering issues by label performance --- app/controllers/concerns/issues_action.rb | 2 - .../concerns/merge_requests_action.rb | 1 - app/finders/issuable_finder.rb | 17 +-- changelogs/unreleased/issue_40500.yml | 5 + .../development/22_labeled_issues_seed.rb | 112 ++++++++++++++++++ 5 files changed, 123 insertions(+), 14 deletions(-) create mode 100644 changelogs/unreleased/issue_40500.yml create mode 100644 db/fixtures/development/22_labeled_issues_seed.rb diff --git a/app/controllers/concerns/issues_action.rb b/app/controllers/concerns/issues_action.rb index d4cccbe6442..3ba1235cee0 100644 --- a/app/controllers/concerns/issues_action.rb +++ b/app/controllers/concerns/issues_action.rb @@ -5,8 +5,6 @@ module IssuesAction # rubocop:disable Gitlab/ModuleWithInstanceVariables def issues @finder_type = IssuesFinder - @label = finder.labels.first - @issues = issuables_collection .non_archived .page(params[:page]) diff --git a/app/controllers/concerns/merge_requests_action.rb b/app/controllers/concerns/merge_requests_action.rb index 4d44df3bba9..a9cc13038bf 100644 --- a/app/controllers/concerns/merge_requests_action.rb +++ b/app/controllers/concerns/merge_requests_action.rb @@ -5,7 +5,6 @@ module MergeRequestsAction # rubocop:disable Gitlab/ModuleWithInstanceVariables def merge_requests @finder_type = MergeRequestsFinder - @label = finder.labels.first @merge_requests = issuables_collection.page(params[:page]) diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index b46ec5e5350..493e7985d75 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -374,19 +374,14 @@ class IssuableFinder end def by_label(items) - if labels? - if filter_by_no_label? - items = items.without_label - else - items = items.with_label(label_names, params[:sort]) - items_projects = projects(items) + return items unless labels? - if items_projects - label_ids = LabelsFinder.new(current_user, project_ids: items_projects).execute(skip_authorization: true).select(:id) - items = items.where(labels: { id: label_ids }) - end + items = + if filter_by_no_label? + items.without_label + else + items.with_label(label_names, params[:sort]) end - end items end diff --git a/changelogs/unreleased/issue_40500.yml b/changelogs/unreleased/issue_40500.yml new file mode 100644 index 00000000000..35e8938fdad --- /dev/null +++ b/changelogs/unreleased/issue_40500.yml @@ -0,0 +1,5 @@ +--- +title: Fix timeout when filtering issues by label +merge_request: +author: +type: performance diff --git a/db/fixtures/development/22_labeled_issues_seed.rb b/db/fixtures/development/22_labeled_issues_seed.rb new file mode 100644 index 00000000000..3e4485c7a73 --- /dev/null +++ b/db/fixtures/development/22_labeled_issues_seed.rb @@ -0,0 +1,112 @@ +# Creates a project with labeled issues for a user. +# Run this single seed file using: rake db:seed_fu FILTER=labeled USER_ID=74. +# If an USER_ID is not provided it will use the last created user. +require './spec/support/sidekiq' + +class Gitlab::Seeder::LabeledIssues + include ::Gitlab::Utils + + def initialize(user) + @user = user + end + + def seed! + Sidekiq::Testing.inline! do + group = create_group + puts '.' + + create_projects(group) + puts '.' + + create_labels(group) + puts '.' + + create_issues(group) + puts '.' + end + + print '.' + end + + private + + def create_group + group_name = "group_of_#{@user.name}#{SecureRandom.hex(4)}" + + group = Group.new( + name: group_name, + path: group_name, + description: FFaker::Lorem.sentence + ) + + group.save + + group.add_owner(@user) + + group + end + + def create_projects(group) + 5.times do + project_name = "project_#{SecureRandom.hex(6)}" + params = { + namespace_id: group.id, + name: project_name, + description: FFaker::Lorem.sentence, + visibility_level: Gitlab::VisibilityLevel.values.sample + } + + Projects::CreateService.new(@user, params).execute + end + end + + def create_labels(group) + group.projects.each do |project| + 5.times do + label_title = FFaker::Vehicle.model + Labels::CreateService.new(title: label_title).execute(project: project) + end + end + + 10.times do + label_title = FFaker::Product.brand + Labels::CreateService.new(title: label_title).execute(group: group) + end + end + + def create_issues(group) + # Get only group labels + group_labels = + LabelsFinder.new(@user, group_id: group.id).execute.where.not(group_id: nil) + + group.projects.each do |project| + label_ids = project.labels.pluck(:id).sample(5) + label_ids.push(*group.labels.sample(4)) + + 50.times do + issue_params = { + title: FFaker::Lorem.sentence(6), + description: FFaker::Lorem.sentence, + state: 'opened', + label_ids: label_ids + + } + + Issues::CreateService.new(project, @user, issue_params).execute if project.project_feature.present? + end + end + end +end + +Gitlab::Seeder.quiet do + user_id = ENV['USER_ID'] + + user = + if user_id.present? + User.find(user_id) + else + User.last + end + + Gitlab::Seeder::LabeledIssues.new(user).seed! +end