summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Lopez <james@jameslopez.es>2017-05-05 09:40:44 +0200
committerJames Lopez <james@jameslopez.es>2017-05-05 09:40:44 +0200
commit1fe8b7f646603239f530b1a18427f4f5bc0e2060 (patch)
treefa275d07c21332c15e5de6ad87fdc19f55570d78
parentcf002738e766f977bdb0e857759f548a5c65c9bd (diff)
downloadgitlab-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.rb32
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