From 85d89b472dff2c3d06801dbd42f91c325d21a434 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 8 Sep 2016 20:36:01 +0200 Subject: Optimized n+1 queries in accounts Atom and HTML views Added stack trace for SQL queries in development Removed badly thought out accounts/lookup API --- app/controllers/accounts_controller.rb | 17 ++++++++++++----- app/controllers/api/accounts/lookup_controller.rb | 14 -------------- app/helpers/api/accounts/lookup_helper.rb | 2 -- app/helpers/application_helper.rb | 19 +++++++++++-------- app/helpers/stream_entries_helper.rb | 4 ++-- app/models/status.rb | 2 +- app/models/stream_entry.rb | 12 +++++++++++- 7 files changed, 37 insertions(+), 33 deletions(-) delete mode 100644 app/controllers/api/accounts/lookup_controller.rb delete mode 100644 app/helpers/api/accounts/lookup_helper.rb (limited to 'app') diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 3c02e0bec..c10a2c680 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -6,14 +6,21 @@ class AccountsController < ApplicationController def show respond_to do |format| - format.html { @statuses = @account.statuses.order('id desc').with_includes.with_counters.paginate(page: params[:page], per_page: 10)} + format.html do + @statuses = @account.statuses.order('id desc').with_includes.with_counters.paginate(page: params[:page], per_page: 10) + + if user_signed_in? + status_ids = @statuses.collect { |s| [s.id, s.reblog_of_id] }.flatten.uniq + @favourited = Favourite.where(status_id: status_ids).where(account_id: current_user.account_id).map { |f| [f.status_id, true] }.to_h + @reblogged = Status.where(reblog_of_id: status_ids).where(account_id: current_user.account_id).map { |s| [s.reblog_of_id, true] }.to_h + else + @favourited = {} + @reblogged = {} + end + end format.atom do @entries = @account.stream_entries.order('id desc').with_includes.paginate_by_max_id(20, params[:max_id] || nil) - - ActiveRecord::Associations::Preloader.new.preload(@entries.select { |a| a.activity_type == 'Status' }, activity: [:mentions, :media_attachments, reblog: :account, thread: :account]) - ActiveRecord::Associations::Preloader.new.preload(@entries.select { |a| a.activity_type == 'Favourite' }, activity: [:account, :status]) - ActiveRecord::Associations::Preloader.new.preload(@entries.select { |a| a.activity_type == 'Follow' }, activity: :target_account) end end end diff --git a/app/controllers/api/accounts/lookup_controller.rb b/app/controllers/api/accounts/lookup_controller.rb deleted file mode 100644 index 319401a2e..000000000 --- a/app/controllers/api/accounts/lookup_controller.rb +++ /dev/null @@ -1,14 +0,0 @@ -class Api::Accounts::LookupController < ApiController - before_action :doorkeeper_authorize! - respond_to :json - - def index - @accounts = Account.where(domain: nil).where(username: lookup_params) - end - - private - - def lookup_params - (params[:usernames] || '').split(',').map(&:strip) - end -end diff --git a/app/helpers/api/accounts/lookup_helper.rb b/app/helpers/api/accounts/lookup_helper.rb deleted file mode 100644 index 5caf0e28c..000000000 --- a/app/helpers/api/accounts/lookup_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module Api::Accounts::LookupHelper -end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index e0105ee54..e43875544 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -22,23 +22,26 @@ module ApplicationHelper def account_from_mentions(search_string, mentions) mentions.each { |x| return x.account if x.account.acct.eql?(search_string) } + nil # If that was unsuccessful, try fetching user from db separately # But this shouldn't ever happen if the mentions were created correctly! - username, domain = search_string.split('@') + # username, domain = search_string.split('@') - if domain == Rails.configuration.x.local_domain - account = Account.find_local(username) - else - account = Account.find_remote(username, domain) - end + # if domain == Rails.configuration.x.local_domain + # account = Account.find_local(username) + # else + # account = Account.find_remote(username, domain) + # end - account + # account end def linkify(status) auto_link(HTMLEntities.new.encode(status.text), link: :urls, html: { rel: 'nofollow noopener' }).gsub(Account::MENTION_RE) do |m| - if account = account_from_mentions(Account::MENTION_RE.match(m)[1], status.mentions) + account = account_from_mentions(Account::MENTION_RE.match(m)[1], status.mentions) + + unless account.nil? "#{m.split('@').first}@#{account.acct}" else m diff --git a/app/helpers/stream_entries_helper.rb b/app/helpers/stream_entries_helper.rb index a29014d1b..ce77206ea 100644 --- a/app/helpers/stream_entries_helper.rb +++ b/app/helpers/stream_entries_helper.rb @@ -21,11 +21,11 @@ module StreamEntriesHelper end def reblogged_by_me_class(status) - user_signed_in? && current_user.account.reblogged?(status) ? 'reblogged' : '' + user_signed_in? && @reblogged.has_key?(status.id) ? 'reblogged' : '' end def favourited_by_me_class(status) - user_signed_in? && current_user.account.favourited?(status) ? 'favourited' : '' + user_signed_in? && @favourited.has_key?(status.id) ? 'favourited' : '' end def proper_status(status) diff --git a/app/models/status.rb b/app/models/status.rb index df9eceaff..12c58733c 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -18,7 +18,7 @@ class Status < ApplicationRecord validates :text, presence: true, if: Proc.new { |s| s.local? && !s.reblog? } scope :with_counters, -> { select('statuses.*, (select count(r.id) from statuses as r where r.reblog_of_id = statuses.id) as reblogs_count, (select count(f.id) from favourites as f where f.status_id = statuses.id) as favourites_count') } - scope :with_includes, -> { includes(:account, :mentions, :media_attachments, :stream_entry, reblog: [:account, :mentions], thread: :account) } + scope :with_includes, -> { includes(:account, :media_attachments, :stream_entry, mentions: :account, reblog: [:account, mentions: :account], thread: :account) } def local? self.uri.nil? diff --git a/app/models/stream_entry.rb b/app/models/stream_entry.rb index 165f62f20..f33295796 100644 --- a/app/models/stream_entry.rb +++ b/app/models/stream_entry.rb @@ -4,9 +4,15 @@ class StreamEntry < ApplicationRecord belongs_to :account, inverse_of: :stream_entries belongs_to :activity, polymorphic: true + belongs_to :status, foreign_type: 'Status', foreign_key: 'activity_id' + belongs_to :follow, foreign_type: 'Follow', foreign_key: 'activity_id' + belongs_to :favourite, foreign_type: 'Favourite', foreign_key: 'activity_id' + validates :account, :activity, presence: true - scope :with_includes, -> { includes(:activity) } + STATUS_INCLUDES = [:account, :stream_entry, :media_attachments, mentions: :account, reblog: [:stream_entry, :account, mentions: :account], thread: [:stream_entry, :account]] + + scope :with_includes, -> { includes(:account, status: STATUS_INCLUDES, favourite: [:account, :stream_entry, status: STATUS_INCLUDES], follow: [:target_account, :stream_entry]) } def object_type orphaned? ? :activity : (targeted? ? :activity : self.activity.object_type) @@ -44,6 +50,10 @@ class StreamEntry < ApplicationRecord self.activity.respond_to?(:mentions) ? self.activity.mentions.map { |x| x.account } : [] end + def activity + self.send(self.activity_type.downcase.to_sym) + end + private def orphaned? -- cgit