0
0
Fork 0

Fix n+1 queries in StatusThreadingConcern (#7321)

This commit is contained in:
Eugen Rochko 2018-05-03 10:41:58 +02:00 committed by GitHub
parent a3d84e705a
commit a5293fdf61
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 20 deletions

View file

@ -20,6 +20,10 @@ module AccountInteractions
follow_mapping(Block.where(target_account_id: target_account_ids, account_id: account_id), :target_account_id)
end
def blocked_by_map(target_account_ids, account_id)
follow_mapping(Block.where(account_id: target_account_ids, target_account_id: account_id), :account_id)
end
def muting_map(target_account_ids, account_id)
Mute.where(target_account_id: target_account_ids, account_id: account_id).each_with_object({}) do |mute, mapping|
mapping[mute.target_account_id] = {
@ -38,8 +42,12 @@ module AccountInteractions
def domain_blocking_map(target_account_ids, account_id)
accounts_map = Account.where(id: target_account_ids).select('id, domain').map { |a| [a.id, a.domain] }.to_h
blocked_domains = AccountDomainBlock.where(account_id: account_id, domain: accounts_map.values).pluck(:domain)
accounts_map.map { |id, domain| [id, blocked_domains.include?(domain)] }.to_h
blocked_domains = domain_blocking_map_by_domain(accounts_map.values.compact, account_id)
accounts_map.map { |id, domain| [id, blocked_domains[domain]] }.to_h
end
def domain_blocking_map_by_domain(target_domains, account_id)
follow_mapping(AccountDomainBlock.where(account_id: account_id, domain: target_domains), :domain)
end
private

View file

@ -71,10 +71,21 @@ module StatusThreadingConcern
end
def find_statuses_from_tree_path(ids, account)
statuses = statuses_with_accounts(ids).to_a
statuses = statuses_with_accounts(ids).to_a
account_ids = statuses.map(&:account_id).uniq
domains = statuses.map(&:account_domain).compact.uniq
# FIXME: n+1 bonanza
statuses.reject! { |status| filter_from_context?(status, account) }
relations = if account.present?
{
blocking: Account.blocking_map(account_ids, account.id),
blocked_by: Account.blocked_by_map(account_ids, account.id),
muting: Account.muting_map(account_ids, account.id),
following: Account.following_map(account_ids, account.id),
domain_blocking_by_domain: Account.domain_blocking_map_by_domain(domains, account.id),
}
end
statuses.reject! { |status| filter_from_context?(status, account, relations) }
# Order ancestors/descendants by tree path
statuses.sort_by! { |status| ids.index(status.id) }
@ -84,7 +95,7 @@ module StatusThreadingConcern
Status.where(id: ids).includes(:account)
end
def filter_from_context?(status, account)
StatusFilter.new(status, account).filtered?
def filter_from_context?(status, account, relations)
StatusFilter.new(status, account, relations).filtered?
end
end