Fix performances of profile directory (#26842)

th-downstream
Claire 1 year ago committed by GitHub
parent e654e8e07e
commit d45dd56874

@ -125,7 +125,7 @@ class Account < ApplicationRecord
scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) } scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) }
scope :without_unapproved, -> { left_outer_joins(:user).merge(User.approved.confirmed).or(remote) } scope :without_unapproved, -> { left_outer_joins(:user).merge(User.approved.confirmed).or(remote) }
scope :searchable, -> { without_unapproved.without_suspended.where(moved_to_account_id: nil) } scope :searchable, -> { without_unapproved.without_suspended.where(moved_to_account_id: nil) }
scope :discoverable, -> { searchable.without_silenced.where(discoverable: true).left_outer_joins(:account_stat) } scope :discoverable, -> { searchable.without_silenced.where(discoverable: true).joins(:account_stat) }
scope :followable_by, ->(account) { joins(arel_table.join(Follow.arel_table, Arel::Nodes::OuterJoin).on(arel_table[:id].eq(Follow.arel_table[:target_account_id]).and(Follow.arel_table[:account_id].eq(account.id))).join_sources).where(Follow.arel_table[:id].eq(nil)).joins(arel_table.join(FollowRequest.arel_table, Arel::Nodes::OuterJoin).on(arel_table[:id].eq(FollowRequest.arel_table[:target_account_id]).and(FollowRequest.arel_table[:account_id].eq(account.id))).join_sources).where(FollowRequest.arel_table[:id].eq(nil)) } scope :followable_by, ->(account) { joins(arel_table.join(Follow.arel_table, Arel::Nodes::OuterJoin).on(arel_table[:id].eq(Follow.arel_table[:target_account_id]).and(Follow.arel_table[:account_id].eq(account.id))).join_sources).where(Follow.arel_table[:id].eq(nil)).joins(arel_table.join(FollowRequest.arel_table, Arel::Nodes::OuterJoin).on(arel_table[:id].eq(FollowRequest.arel_table[:target_account_id]).and(FollowRequest.arel_table[:account_id].eq(account.id))).join_sources).where(FollowRequest.arel_table[:id].eq(nil)) }
scope :by_recent_status, -> { order(Arel.sql('account_stats.last_status_at DESC NULLS LAST')) } scope :by_recent_status, -> { order(Arel.sql('account_stats.last_status_at DESC NULLS LAST')) }
scope :by_recent_sign_in, -> { order(Arel.sql('users.current_sign_in_at DESC NULLS LAST')) } scope :by_recent_sign_in, -> { order(Arel.sql('users.current_sign_in_at DESC NULLS LAST')) }

@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddIndexAccountStatsOnLastStatusAtAndAccountId < ActiveRecord::Migration[7.0]
disable_ddl_transaction!
def change
add_index :account_stats, [:last_status_at, :account_id], order: { last_status_at: 'DESC NULLS LAST' }, algorithm: :concurrently
end
end

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2023_09_04_134623) do ActiveRecord::Schema[7.0].define(version: 2023_09_07_150100) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -99,6 +99,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_09_04_134623) do
t.datetime "updated_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false
t.datetime "last_status_at", precision: nil t.datetime "last_status_at", precision: nil
t.index ["account_id"], name: "index_account_stats_on_account_id", unique: true t.index ["account_id"], name: "index_account_stats_on_account_id", unique: true
t.index ["last_status_at", "account_id"], name: "index_account_stats_on_last_status_at_and_account_id", order: { last_status_at: "DESC NULLS LAST" }
end end
create_table "account_statuses_cleanup_policies", force: :cascade do |t| create_table "account_statuses_cleanup_policies", force: :cascade do |t|

@ -15,12 +15,13 @@ describe Api::V1::DirectoriesController do
describe 'GET #show' do describe 'GET #show' do
context 'with no params' do context 'with no params' do
before do before do
_local_unconfirmed_account = Fabricate( local_unconfirmed_account = Fabricate(
:account, :account,
domain: nil, domain: nil,
user: Fabricate(:user, confirmed_at: nil, approved: true), user: Fabricate(:user, confirmed_at: nil, approved: true),
username: 'local_unconfirmed' username: 'local_unconfirmed'
) )
local_unconfirmed_account.create_account_stat!
local_unapproved_account = Fabricate( local_unapproved_account = Fabricate(
:account, :account,
@ -28,15 +29,17 @@ describe Api::V1::DirectoriesController do
user: Fabricate(:user, confirmed_at: 10.days.ago), user: Fabricate(:user, confirmed_at: 10.days.ago),
username: 'local_unapproved' username: 'local_unapproved'
) )
local_unapproved_account.create_account_stat!
local_unapproved_account.user.update(approved: false) local_unapproved_account.user.update(approved: false)
_local_undiscoverable_account = Fabricate( local_undiscoverable_account = Fabricate(
:account, :account,
domain: nil, domain: nil,
user: Fabricate(:user, confirmed_at: 10.days.ago, approved: true), user: Fabricate(:user, confirmed_at: 10.days.ago, approved: true),
discoverable: false, discoverable: false,
username: 'local_undiscoverable' username: 'local_undiscoverable'
) )
local_undiscoverable_account.create_account_stat!
excluded_from_timeline_account = Fabricate( excluded_from_timeline_account = Fabricate(
:account, :account,
@ -44,14 +47,16 @@ describe Api::V1::DirectoriesController do
discoverable: true, discoverable: true,
username: 'remote_excluded_from_timeline' username: 'remote_excluded_from_timeline'
) )
excluded_from_timeline_account.create_account_stat!
Fabricate(:block, account: user.account, target_account: excluded_from_timeline_account) Fabricate(:block, account: user.account, target_account: excluded_from_timeline_account)
_domain_blocked_account = Fabricate( domain_blocked_account = Fabricate(
:account, :account,
domain: 'test.example', domain: 'test.example',
discoverable: true, discoverable: true,
username: 'remote_domain_blocked' username: 'remote_domain_blocked'
) )
domain_blocked_account.create_account_stat!
Fabricate(:account_domain_block, account: user.account, domain: 'test.example') Fabricate(:account_domain_block, account: user.account, domain: 'test.example')
end end
@ -63,6 +68,7 @@ describe Api::V1::DirectoriesController do
discoverable: true, discoverable: true,
username: 'local_discoverable' username: 'local_discoverable'
) )
local_discoverable_account.create_account_stat!
eligible_remote_account = Fabricate( eligible_remote_account = Fabricate(
:account, :account,
@ -70,6 +76,7 @@ describe Api::V1::DirectoriesController do
discoverable: true, discoverable: true,
username: 'eligible_remote' username: 'eligible_remote'
) )
eligible_remote_account.create_account_stat!
get :show get :show
@ -84,6 +91,8 @@ describe Api::V1::DirectoriesController do
user = Fabricate(:user, confirmed_at: 10.days.ago, approved: true) user = Fabricate(:user, confirmed_at: 10.days.ago, approved: true)
local_account = Fabricate(:account, domain: nil, user: user) local_account = Fabricate(:account, domain: nil, user: user)
remote_account = Fabricate(:account, domain: 'host.example') remote_account = Fabricate(:account, domain: 'host.example')
local_account.create_account_stat!
remote_account.create_account_stat!
get :show, params: { local: '1' } get :show, params: { local: '1' }
@ -110,9 +119,9 @@ describe Api::V1::DirectoriesController do
context 'when ordered by new' do context 'when ordered by new' do
it 'returns accounts in order of creation' do it 'returns accounts in order of creation' do
account_old = Fabricate(:account) account_old = Fabricate(:account_stat).account
travel_to 10.seconds.from_now travel_to 10.seconds.from_now
account_new = Fabricate(:account) account_new = Fabricate(:account_stat).account
get :show, params: { order: 'new' } get :show, params: { order: 'new' }

Loading…
Cancel
Save