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
path: root/app
diff options
context:
space:
mode:
authorMarkus Koller <mkoller@gitlab.com>2019-09-02 14:12:20 +0300
committerMarkus Koller <mkoller@gitlab.com>2019-09-10 16:24:28 +0300
commit60755fbc406bd25ab526339899f97a2b27aeb272 (patch)
treea60f6fa9beb0c4ccdc27c5f7734c14bc34ad2d21 /app
parent08b0613302ec813c0735e2c0447a3f7683d7ab87 (diff)
Optimize queries for snippet listings
- Avoid N+1 queries for authors and comment counts - Avoid an additional snippet existence query
Diffstat (limited to 'app')
-rw-r--r--app/controllers/dashboard/snippets_controller.rb14
-rw-r--r--app/controllers/explore/snippets_controller.rb10
-rw-r--r--app/controllers/projects/snippets_controller.rb16
-rw-r--r--app/controllers/snippets_controller.rb7
-rw-r--r--app/controllers/users_controller.rb12
-rw-r--r--app/models/concerns/noteable.rb4
-rw-r--r--app/models/snippet.rb1
-rw-r--r--app/views/shared/snippets/_list.html.haml7
-rw-r--r--app/views/shared/snippets/_snippet.html.haml6
9 files changed, 49 insertions, 28 deletions
diff --git a/app/controllers/dashboard/snippets_controller.rb b/app/controllers/dashboard/snippets_controller.rb
index 161c22046f9..382f54c6c00 100644
--- a/app/controllers/dashboard/snippets_controller.rb
+++ b/app/controllers/dashboard/snippets_controller.rb
@@ -1,14 +1,16 @@
# frozen_string_literal: true
class Dashboard::SnippetsController < Dashboard::ApplicationController
+ include Gitlab::NoteableMetadata
+
skip_cross_project_access_check :index
def index
- @snippets = SnippetsFinder.new(
- current_user,
- author: current_user,
- scope: params[:scope]
- ).execute
- @snippets = @snippets.page(params[:page])
+ @snippets = SnippetsFinder.new(current_user, author: current_user, scope: params[:scope])
+ .execute
+ .page(params[:page])
+ .inc_author
+
+ @noteable_meta_data = noteable_meta_data(@snippets, 'Snippet')
end
end
diff --git a/app/controllers/explore/snippets_controller.rb b/app/controllers/explore/snippets_controller.rb
index 76ed142c939..6192b594593 100644
--- a/app/controllers/explore/snippets_controller.rb
+++ b/app/controllers/explore/snippets_controller.rb
@@ -1,8 +1,14 @@
# frozen_string_literal: true
class Explore::SnippetsController < Explore::ApplicationController
+ include Gitlab::NoteableMetadata
+
def index
- @snippets = SnippetsFinder.new(current_user).execute
- @snippets = @snippets.page(params[:page])
+ @snippets = SnippetsFinder.new(current_user)
+ .execute
+ .page(params[:page])
+ .inc_author
+
+ @noteable_meta_data = noteable_meta_data(@snippets, 'Snippet')
end
end
diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb
index 59f948959d6..c84e9fbc2d7 100644
--- a/app/controllers/projects/snippets_controller.rb
+++ b/app/controllers/projects/snippets_controller.rb
@@ -6,6 +6,7 @@ class Projects::SnippetsController < Projects::ApplicationController
include SpammableActions
include SnippetsActions
include RendersBlob
+ include Gitlab::NoteableMetadata
skip_before_action :verify_authenticity_token,
if: -> { action_name == 'show' && js_request? }
@@ -28,15 +29,16 @@ class Projects::SnippetsController < Projects::ApplicationController
respond_to :html
def index
- @snippets = SnippetsFinder.new(
- current_user,
- project: @project,
- scope: params[:scope]
- ).execute
- @snippets = @snippets.page(params[:page])
+ @snippets = SnippetsFinder.new(current_user, project: @project, scope: params[:scope])
+ .execute
+ .page(params[:page])
+ .inc_author
+
if @snippets.out_of_range? && @snippets.total_pages != 0
- redirect_to project_snippets_path(@project, page: @snippets.total_pages)
+ return redirect_to project_snippets_path(@project, page: @snippets.total_pages)
end
+
+ @noteable_meta_data = noteable_meta_data(@snippets, 'Snippet')
end
def new
diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb
index 869655e9550..c1e05b72b37 100644
--- a/app/controllers/snippets_controller.rb
+++ b/app/controllers/snippets_controller.rb
@@ -7,6 +7,7 @@ class SnippetsController < ApplicationController
include SnippetsActions
include RendersBlob
include PreviewMarkdown
+ include Gitlab::NoteableMetadata
skip_before_action :verify_authenticity_token,
if: -> { action_name == 'show' && js_request? }
@@ -32,7 +33,11 @@ class SnippetsController < ApplicationController
@user = UserFinder.new(params[:username]).find_by_username!
@snippets = SnippetsFinder.new(current_user, author: @user, scope: params[:scope])
- .execute.page(params[:page])
+ .execute
+ .page(params[:page])
+ .inc_author
+
+ @noteable_meta_data = noteable_meta_data(@snippets, 'Snippet')
render 'index'
else
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 91e0efcf45f..e38d4073de3 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -4,6 +4,7 @@ class UsersController < ApplicationController
include RoutableActions
include RendersMemberAccess
include ControllerWithCrossProjectAccessCheck
+ include Gitlab::NoteableMetadata
requires_cross_project_access show: false,
groups: false,
@@ -165,11 +166,12 @@ class UsersController < ApplicationController
end
def load_snippets
- @snippets = SnippetsFinder.new(
- current_user,
- author: user,
- scope: params[:scope]
- ).execute.page(params[:page])
+ @snippets = SnippetsFinder.new(current_user, author: user, scope: params[:scope])
+ .execute
+ .page(params[:page])
+ .inc_author
+
+ @noteable_meta_data = noteable_meta_data(@snippets, 'Snippet')
end
def build_canonical_path(user)
diff --git a/app/models/concerns/noteable.rb b/app/models/concerns/noteable.rb
index 6a44bc7c401..b3e4df730b4 100644
--- a/app/models/concerns/noteable.rb
+++ b/app/models/concerns/noteable.rb
@@ -3,6 +3,10 @@
module Noteable
extend ActiveSupport::Concern
+ # This object is used to gather noteable meta data for list displays
+ # avoiding n+1 queries and improving performance.
+ NoteableMeta = Struct.new(:user_notes_count)
+
class_methods do
# `Noteable` class names that support replying to individual notes.
def replyable_types
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index 00931457344..b2fca65b9e0 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -55,6 +55,7 @@ class Snippet < ApplicationRecord
scope :are_public, -> { where(visibility_level: Snippet::PUBLIC) }
scope :public_and_internal, -> { where(visibility_level: [Snippet::PUBLIC, Snippet::INTERNAL]) }
scope :fresh, -> { order("created_at DESC") }
+ scope :inc_author, -> { includes(:author) }
scope :inc_relations_for_view, -> { includes(author: :status) }
participant :author
diff --git a/app/views/shared/snippets/_list.html.haml b/app/views/shared/snippets/_list.html.haml
index 5d2152eb411..766f48fff3d 100644
--- a/app/views/shared/snippets/_list.html.haml
+++ b/app/views/shared/snippets/_list.html.haml
@@ -1,12 +1,11 @@
- remote = local_assigns.fetch(:remote, false)
- link_project = local_assigns.fetch(:link_project, false)
-- if @snippets.exists?
+- if @snippets.to_a.empty?
+ .nothing-here-block= s_("SnippetsEmptyState|No snippets found")
+- else
.snippets-list-holder
%ul.content-list
= render partial: 'shared/snippets/snippet', collection: @snippets, locals: { link_project: link_project }
= paginate @snippets, theme: 'gitlab', remote: remote
-
-- else
- .nothing-here-block= s_("SnippetsEmptyState|No snippets found")
diff --git a/app/views/shared/snippets/_snippet.html.haml b/app/views/shared/snippets/_snippet.html.haml
index 42af97bc6af..0ef626868a2 100644
--- a/app/views/shared/snippets/_snippet.html.haml
+++ b/app/views/shared/snippets/_snippet.html.haml
@@ -1,4 +1,5 @@
- link_project = local_assigns.fetch(:link_project, false)
+- notes_count = @noteable_meta_data[snippet.id].user_notes_count
%li.snippet-row
= image_tag avatar_icon_for_user(snippet.author), class: "avatar s40 d-none d-sm-block", alt: ''
@@ -12,10 +13,9 @@
%ul.controls
%li
- - note_count = snippet.notes.user.count
- = link_to reliable_snippet_path(snippet, anchor: 'notes'), class: ('no-comments' if note_count.zero?) do
+ = link_to reliable_snippet_path(snippet, anchor: 'notes'), class: ('no-comments' if notes_count.zero?) do
= icon('comments')
- = note_count
+ = notes_count
%li
%span.sr-only
= visibility_level_label(snippet.visibility_level)