diff options
author | Sean McGivern <sean@gitlab.com> | 2018-10-02 17:29:45 +0300 |
---|---|---|
committer | Sean McGivern <sean@gitlab.com> | 2018-10-04 16:28:15 +0300 |
commit | 28e6af88aa16a33717dbdbe870a8423300aef042 (patch) | |
tree | 1fd34b9d217e88b22d5c928d142cf8117f2fd5e6 /spec/services/notification_recipient_service_spec.rb | |
parent | 819ecd5fb01ab64cacc31253c51984a7564949d7 (diff) |
Fix N+1 for notification recipients on private projects
If we don't call #to_a, we're relying on the members already being loaded from
elsewhere. Otherwise we'll do a separate query for each user:
[1] pry(main)> Project.first.team.members.include?(User.first)
Project Load (0.7ms) SELECT "projects".* FROM "projects" ORDER BY "projects"."id" ASC LIMIT 1
↳ (pry):3
User Load (1.8ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1
↳ (pry):3
User Exists (0.6ms) SELECT 1 AS one FROM "users" INNER JOIN "project_authorizations" ON "users"."id" = "project_authorizations"."user_id" WHERE "project_authorizations"."project_id" = $1 AND "users"."id" = $2 LIMIT 1 [["project_id", 1], ["id", 1]]
↳ (pry):3
=> true
[2] pry(main)> Project.first.team.members.to_a.include?(User.first)
Project Load (12.8ms) SELECT "projects".* FROM "projects" ORDER BY "projects"."id" ASC LIMIT 1
↳ (pry):1
User Load (9.6ms) SELECT "users".* FROM "users" INNER JOIN "project_authorizations" ON "users"."id" = "project_authorizations"."user_id" WHERE "project_authorizations"."project_id" = $1 [["project_id", 1]]
↳ (pry):1
User Load (0.6ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1
↳ (pry):1
=> true
Diffstat (limited to 'spec/services/notification_recipient_service_spec.rb')
-rw-r--r-- | spec/services/notification_recipient_service_spec.rb | 44 |
1 files changed, 22 insertions, 22 deletions
diff --git a/spec/services/notification_recipient_service_spec.rb b/spec/services/notification_recipient_service_spec.rb index 9a24821860e..cea5ea125b9 100644 --- a/spec/services/notification_recipient_service_spec.rb +++ b/spec/services/notification_recipient_service_spec.rb @@ -10,18 +10,9 @@ describe NotificationRecipientService do let(:issue) { create(:issue, project: project, assignees: [assignee]) } let(:note) { create(:note_on_issue, noteable: issue, project_id: issue.project_id) } - context 'when there are multiple watchers' do - def create_watcher - watcher = create(:user) - create(:notification_setting, source: project, user: watcher, level: :watch) - - other_projects.each do |other_project| - create(:notification_setting, source: other_project, user: watcher, level: :watch) - end - end - + shared_examples 'no N+1 queries' do it 'avoids N+1 queries', :request_store do - create_watcher + create_user service.build_new_note_recipients(note) @@ -29,30 +20,39 @@ describe NotificationRecipientService do service.build_new_note_recipients(note) end - create_watcher + create_user expect { service.build_new_note_recipients(note) }.not_to exceed_query_limit(control_count) end end + context 'when there are multiple watchers' do + def create_user + watcher = create(:user) + create(:notification_setting, source: project, user: watcher, level: :watch) + + other_projects.each do |other_project| + create(:notification_setting, source: other_project, user: watcher, level: :watch) + end + end + + include_examples 'no N+1 queries' + end + context 'when there are multiple subscribers' do - def create_subscriber + def create_user subscriber = create(:user) issue.subscriptions.create(user: subscriber, project: project, subscribed: true) end - it 'avoids N+1 queries' do - create_subscriber + include_examples 'no N+1 queries' - service.build_new_note_recipients(note) - - control_count = ActiveRecord::QueryRecorder.new do - service.build_new_note_recipients(note) + context 'when the project is private' do + before do + project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) end - create_subscriber - - expect { service.build_new_note_recipients(note) }.not_to exceed_query_limit(control_count) + include_examples 'no N+1 queries' end end end |