Commit 7d2859e9 authored by Andreas Brandl's avatar Andreas Brandl

Leverage user_contributed_projects to find recent events.

Closes #40525.
parent 7e7f260d
...@@ -12,6 +12,8 @@ class UserRecentEventsFinder ...@@ -12,6 +12,8 @@ class UserRecentEventsFinder
attr_reader :current_user, :target_user, :params attr_reader :current_user, :target_user, :params
LIMIT = 20
def initialize(current_user, target_user, params = {}) def initialize(current_user, target_user, params = {})
@current_user = current_user @current_user = current_user
@target_user = target_user @target_user = target_user
...@@ -19,15 +21,44 @@ class UserRecentEventsFinder ...@@ -19,15 +21,44 @@ class UserRecentEventsFinder
end end
def execute def execute
target_user recent_events(params[:offset] || 0)
.recent_events .joins(:project)
.merge(projects_for_current_user)
.references(:project)
.with_associations .with_associations
.limit_recent(20, params[:offset]) .limit_recent(LIMIT, params[:offset])
end
private
def recent_events(offset)
sql = <<~SQL
(#{projects}) AS projects_for_join
JOIN (#{target_events.to_sql}) AS #{Event.table_name}
ON #{Event.table_name}.project_id = projects_for_join.id
SQL
# Workaround for https://github.com/rails/rails/issues/24193
Event.from([Arel.sql(sql)])
end end
def projects_for_current_user def target_events
ProjectsFinder.new(current_user: current_user).execute Event.where(author: target_user)
end
def projects
# Compile a list of projects `current_user` interacted with
# and `target_user` is allowed to see.
authorized = target_user
.project_interactions
.joins(:project_authorizations)
.where(project_authorizations: { user: current_user })
.select(:id)
visible = target_user
.project_interactions
.where(visibility_level: [Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PUBLIC])
.select(:id)
Gitlab::SQL::Union.new([authorized, visible]).to_sql
end end
end end
...@@ -114,13 +114,15 @@ class User < ActiveRecord::Base ...@@ -114,13 +114,15 @@ class User < ActiveRecord::Base
has_many :project_authorizations has_many :project_authorizations
has_many :authorized_projects, through: :project_authorizations, source: :project has_many :authorized_projects, through: :project_authorizations, source: :project
has_many :user_interacted_projects
has_many :project_interactions, through: :user_interacted_projects, source: :project, class_name: 'Project'
has_many :snippets, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :snippets, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent
has_many :notes, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :notes, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent
has_many :issues, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :issues, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent
has_many :merge_requests, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :merge_requests, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent
has_many :events, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :events, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent
has_many :subscriptions, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :subscriptions, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :recent_events, -> { order "id DESC" }, foreign_key: :author_id, class_name: "Event"
has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_one :abuse_report, dependent: :destroy, foreign_key: :user_id # rubocop:disable Cop/ActiveRecordDependent has_one :abuse_report, dependent: :destroy, foreign_key: :user_id # rubocop:disable Cop/ActiveRecordDependent
has_many :reported_abuse_reports, dependent: :destroy, foreign_key: :reporter_id, class_name: "AbuseReport" # rubocop:disable Cop/ActiveRecordDependent has_many :reported_abuse_reports, dependent: :destroy, foreign_key: :reporter_id, class_name: "AbuseReport" # rubocop:disable Cop/ActiveRecordDependent
......
---
title: Improve database response time for user activity listing.
merge_request: 17454
author:
type: performance
...@@ -27,7 +27,6 @@ describe User do ...@@ -27,7 +27,6 @@ describe User do
it { is_expected.to have_many(:keys).dependent(:destroy) } it { is_expected.to have_many(:keys).dependent(:destroy) }
it { is_expected.to have_many(:deploy_keys).dependent(:destroy) } it { is_expected.to have_many(:deploy_keys).dependent(:destroy) }
it { is_expected.to have_many(:events).dependent(:destroy) } it { is_expected.to have_many(:events).dependent(:destroy) }
it { is_expected.to have_many(:recent_events).class_name('Event') }
it { is_expected.to have_many(:issues).dependent(:destroy) } it { is_expected.to have_many(:issues).dependent(:destroy) }
it { is_expected.to have_many(:notes).dependent(:destroy) } it { is_expected.to have_many(:notes).dependent(:destroy) }
it { is_expected.to have_many(:merge_requests).dependent(:destroy) } it { is_expected.to have_many(:merge_requests).dependent(:destroy) }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment