Improve speed of global activities fetching query [SCI-4330]

This commit is contained in:
Oleksii Kriuchykhin 2020-02-07 13:53:25 +01:00
parent 7ad3527338
commit 6f8f89fbf0
7 changed files with 49 additions and 32 deletions

View file

@ -5,20 +5,24 @@ class ActivitiesService
# Create condition for view permissions checking first # Create condition for view permissions checking first
visible_teams = user.teams.where(id: teams) visible_teams = user.teams.where(id: teams)
visible_projects = Project.viewable_by_user(user, visible_teams) visible_projects = Project.viewable_by_user(user, visible_teams)
query = Activity.where(project: visible_projects) visible_by_teams = Activity.where(project: nil, team_id: visible_teams.pluck(:id))
.or(Activity.where(project: nil, team: visible_teams)) .order(created_at: :desc)
visible_by_projects = Activity.where(project_id: visible_projects.pluck(:id))
.order(created_at: :desc)
query = Activity.from("((#{visible_by_teams.to_sql}) UNION ALL (#{visible_by_projects.to_sql})) AS activities")
if filters[:subjects].present? if filters[:subjects].present?
subjects_with_children = load_subjects_children(filters[:subjects]) subjects_with_children = load_subjects_children(filters[:subjects])
if subjects_with_children[:Project] if subjects_with_children[:project]
query = query.where('project_id IN (?)', subjects_with_children[:Project]) query = query.where('project_id IN (?)', subjects_with_children[:project])
subjects_with_children.except!(:Project) subjects_with_children.except!(:project)
end end
where_condition = subjects_with_children.map { '(subject_type = ? AND subject_id IN(?))' }.join(' OR ') where_condition = subjects_with_children.map { '(subject_type = ? AND subject_id IN(?))' }.join(' OR ')
where_arguments = subjects_with_children.flatten where_arguments = subjects_with_children.flatten
if subjects_with_children[:MyModule] if subjects_with_children[:my_module]
where_condition = where_condition.concat(' OR (my_module_id IN(?))') where_condition = where_condition.concat(' OR (my_module_id IN(?))')
where_arguments << subjects_with_children[:MyModule] where_arguments << subjects_with_children[:my_module]
end end
query = query.where(where_condition, *where_arguments) query = query.where(where_condition, *where_arguments)
end end
@ -45,12 +49,11 @@ class ActivitiesService
end end
def self.load_subjects_children(subjects = {}) def self.load_subjects_children(subjects = {})
subject_types = Extends::ACTIVITY_SUBJECT_CHILDREN Extends::ACTIVITY_SUBJECT_CHILDREN.each do |subject_name, children|
subject_types.each do |subject_name, children|
next unless children && subjects[subject_name] next unless children && subjects[subject_name]
children.each do |child| children.each do |child|
parent_model = subject_name.to_s.constantize parent_model = subject_name.to_s.camelize.constantize
child_model = parent_model.reflect_on_association(child).class_name.to_sym child_model = parent_model.reflect_on_association(child).class_name.to_sym
next if subjects[child_model] next if subjects[child_model]
@ -64,7 +67,7 @@ class ActivitiesService
end end
def self.my_module_activities(my_module) def self.my_module_activities(my_module)
subjects_with_children = load_subjects_children(MyModule: [my_module.id]) subjects_with_children = load_subjects_children(my_module: [my_module.id])
query = Activity.where(project: my_module.experiment.project) query = Activity.where(project: my_module.experiment.project)
query.where( query.where(
subjects_with_children.map { '(subject_type = ? AND subject_id IN(?))' }.join(' OR '), subjects_with_children.map { '(subject_type = ? AND subject_id IN(?))' }.join(' OR '),

View file

@ -5,8 +5,6 @@
<%= render partial: "top_pane" %> <%= render partial: "top_pane" %>
</div> </div>
<div class="ga-bottom"> <div class="ga-bottom">
<div class="ga-main"> <div class="ga-main">
<div class="activities-container perfect-scrollbar"> <div class="activities-container perfect-scrollbar">
<div class="no-activities-message text-center <%= 'hidden' if @grouped_activities.keys.any? %>"> <div class="no-activities-message text-center <%= 'hidden' if @grouped_activities.keys.any? %>">
@ -26,13 +24,11 @@
<div id="ga-more-activities-placeholder" class="hidden"></div> <div id="ga-more-activities-placeholder" class="hidden"></div>
</div> </div>
</div> </div>
<div class="ga-side"> <div class="ga-side">
<div class="filters-container perfect-scrollbar"> <div class="filters-container perfect-scrollbar">
<%= render partial: "side_filters" %> <%= render partial: "side_filters" %>
</div> </div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -121,15 +121,15 @@ class Extends
).freeze ).freeze
ACTIVITY_SUBJECT_CHILDREN = { ACTIVITY_SUBJECT_CHILDREN = {
Repository: [:repository_rows], repository: [:repository_rows],
RepositoryRow: nil, repository_row: nil,
Report: nil, report: nil,
Project: nil, project: nil,
Experiment: [:my_modules], experiment: [:my_modules],
MyModule: [:results,:protocols], my_module: [:results, :protocols],
Result: nil, result: nil,
Protocol: [:steps], protocol: [:steps],
Step: nil step: nil
} }
ACTIVITY_MESSAGE_ITEMS_TYPES = ACTIVITY_MESSAGE_ITEMS_TYPES =

View file

@ -0,0 +1,18 @@
# frozen_string_literal: true
class FixAndUpdateIndicesOnActivities < ActiveRecord::Migration[6.0]
def up
execute(
"UPDATE activities " \
"SET values = jsonb_set(values, '{\"message_items\", \"asset_name\", \"value_for\"}', '\"file_name\"') " \
"WHERE values @> '{\"message_items\": {\"asset_name\": {\"value_for\": \"file_file_name\"}}}';"
)
add_index :activities, %i(created_at team_id), order: { created_at: :desc, team_id: :asc },
where: 'project_id IS NULL',
name: 'index_activities_on_created_at_and_team_id_and_no_project_id'
end
def down
remove_index :activities, %i(created_at team_id)
end
end

View file

@ -2,7 +2,7 @@ version: '2'
services: services:
db: db:
container_name: scinote_db_production container_name: scinote_db_production
image: postgres:9.6 image: postgres:11
volumes: volumes:
- scinote_production_postgres:/var/lib/postgresql/data - scinote_production_postgres:/var/lib/postgresql/data

View file

@ -2,7 +2,7 @@ version: '2'
services: services:
db: db:
container_name: scinote_db_development container_name: scinote_db_development
image: postgres:9.6 image: postgres:11
volumes: volumes:
- scinote_development_postgres:/var/lib/postgresql/data - scinote_development_postgres:/var/lib/postgresql/data
ports: ports: