From 1fe8b7f646603239f530b1a18427f4f5bc0e2060 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 5 May 2017 09:40:44 +0200 Subject: [PATCH] refactor propagate service to use batch inserts and subquery instead of left join --- app/services/projects/propagate_service.rb | 32 ++++++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/app/services/projects/propagate_service.rb b/app/services/projects/propagate_service.rb index 6e24a67d8b0..b067fc2cd64 100644 --- a/app/services/projects/propagate_service.rb +++ b/app/services/projects/propagate_service.rb @@ -26,7 +26,7 @@ module Projects loop do batch = project_ids_batch(offset) - batch.each { |project_id| create_from_template(project_id) } + bulk_create_from_template(batch) break if batch.size < BATCH_SIZE @@ -34,14 +34,34 @@ module Projects end end - def create_from_template(project_id) - Service.build_from_template(project_id, @template).save! + def bulk_create_from_template(batch) + service_hash_list = batch.map do |project_id| + service_hash.merge('project_id' => project_id) + end + + Project.transaction do + Service.create!(service_hash_list) + end end def project_ids_batch(offset) - Project.joins('LEFT JOIN services ON services.project_id = projects.id'). - where('services.type != ? OR services.id IS NULL', @template.type). - limit(BATCH_SIZE).offset(offset).pluck(:id) + Project.connection.execute( + <<-SQL + SELECT id + FROM projects + WHERE NOT EXISTS ( + SELECT true + FROM services + WHERE services.project_id = projects.id + AND services.type = '#{@template.type}' + ) + LIMIT #{BATCH_SIZE} OFFSET #{offset} + SQL + ).to_a.flatten + end + + def service_hash + @service_hash ||= @template.as_json(methods: :type).except('id', 'template') end end end