diff options
author | James Lopez <james@jameslopez.es> | 2017-05-05 09:40:44 +0200 |
---|---|---|
committer | James Lopez <james@jameslopez.es> | 2017-05-05 09:40:44 +0200 |
commit | 1fe8b7f646603239f530b1a18427f4f5bc0e2060 (patch) | |
tree | fa275d07c21332c15e5de6ad87fdc19f55570d78 | |
parent | cf002738e766f977bdb0e857759f548a5c65c9bd (diff) | |
download | gitlab-ce-1fe8b7f646603239f530b1a18427f4f5bc0e2060.tar.gz |
refactor propagate service to use batch inserts and subquery instead of left join
-rw-r--r-- | app/services/projects/propagate_service.rb | 32 |
1 files 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 |