Commit 8b5553da authored by Mayra Cabrera's avatar Mayra Cabrera

Use a single sql statement for ADO query

Since cluster_projects table does not have a lot of records,
currently it has 11,638, it seems better to use a single sql statement
to update all the records
parent 6fe15fdc
...@@ -6,12 +6,7 @@ class MigrateAutoDevOpsDomainToClusterDomain < ActiveRecord::Migration[5.0] ...@@ -6,12 +6,7 @@ class MigrateAutoDevOpsDomainToClusterDomain < ActiveRecord::Migration[5.0]
DOWNTIME = false DOWNTIME = false
def up def up
domains_info = connection.exec_query(project_auto_devops_query).rows execute(update_clusters_domain_query)
domains_info.each_slice(1_000) do |batch|
update_clusters_query = build_clusters_query(Hash[*batch.flatten])
connection.exec_query(update_clusters_query)
end
end end
def down def down
...@@ -20,59 +15,35 @@ class MigrateAutoDevOpsDomainToClusterDomain < ActiveRecord::Migration[5.0] ...@@ -20,59 +15,35 @@ class MigrateAutoDevOpsDomainToClusterDomain < ActiveRecord::Migration[5.0]
private private
def project_auto_devops_table def update_clusters_domain_query
@project_auto_devops_table ||= ProjectAutoDevops.arel_table if Gitlab::Database.mysql?
mysql_query
else
postgresql_query
end end
def cluster_projects_table
@cluster_projects_table ||= Clusters::Project.arel_table
end end
# Fetches ProjectAutoDevops records with: def mysql_query
# - A domain set <<~HEREDOC
# - With a Clusters::Project related to Project UPDATE clusters, project_auto_devops, cluster_projects
# SET
# Returns an array of arrays like: clusters.domain = project_auto_devops.domain
# => [ WHERE
# [177, "104.198.38.135.nip.io"], cluster_projects.cluster_id = clusters.id
# [178, "35.232.213.111.nip.io"], AND project_auto_devops.project_id = cluster_projects.project_id
# ... AND project_auto_devops.domain != ''
# ] HEREDOC
# Where the first element is the Cluster ID and
# the second element is the domain.
def project_auto_devops_query
project_auto_devops_table.join(cluster_projects_table, Arel::Nodes::OuterJoin)
.on(project_auto_devops_table[:project_id].eq(cluster_projects_table[:project_id]))
.where(project_auto_devops_table[:domain].not_eq(nil).and(project_auto_devops_table[:domain].not_eq('')))
.project(cluster_projects_table[:cluster_id], project_auto_devops_table[:domain])
.to_sql
end end
# Returns an SQL UPDATE query using a CASE statement def postgresql_query
# to update multiple cluster rows with different values.
#
# Example:
# UPDATE clusters
# SET domain = (CASE
# WHEN id = 177 then '104.198.38.135.nip.io'
# WHEN id = 178 then '35.232.213.111.nip.io'
# WHEN id = 179 then '35.232.168.149.nip.io'
# WHEN id = 180 then '35.224.116.88.nip.io'
# END)
# WHERE id IN (177,178,179,180);
def build_clusters_query(cluster_domains_info)
<<~HEREDOC <<~HEREDOC
UPDATE clusters UPDATE clusters
SET domain = (CASE SET domain = project_auto_devops.domain
#{cluster_when_statements(cluster_domains_info)} FROM cluster_projects, project_auto_devops
END) WHERE
WHERE id IN (#{cluster_domains_info.keys.join(",")}); cluster_projects.cluster_id = clusters.id
AND project_auto_devops.project_id = cluster_projects.project_id
AND project_auto_devops.domain != ''
HEREDOC HEREDOC
end end
def cluster_when_statements(cluster_domains_info)
cluster_domains_info.map do |cluster_id, domain|
"WHEN id = #{cluster_id} then '#{domain}'"
end.join("\n")
end
end end
...@@ -46,12 +46,14 @@ describe MigrateAutoDevOpsDomainToClusterDomain, :migration do ...@@ -46,12 +46,14 @@ describe MigrateAutoDevOpsDomainToClusterDomain, :migration do
let(:domain) { 'example-domain.com' } let(:domain) { 'example-domain.com' }
before do before do
setup_cluster_projects_with_domain(quantity: 20, domain: nil) setup_cluster_projects_with_domain(quantity: 25, domain: nil)
end end
it 'should only update specific cluster projects' do it 'should only update specific cluster projects' do
migrate! migrate!
expect(clusters_with_domain.count).to eq(20)
project_auto_devops_with_domain.each do |project_auto_devops| project_auto_devops_with_domain.each do |project_auto_devops|
cluster_project = Clusters::Project.find_by(project_id: project_auto_devops.project_id) cluster_project = Clusters::Project.find_by(project_id: project_auto_devops.project_id)
cluster = Clusters::Cluster.find(cluster_project.cluster_id) cluster = Clusters::Cluster.find(cluster_project.cluster_id)
...@@ -59,6 +61,8 @@ describe MigrateAutoDevOpsDomainToClusterDomain, :migration do ...@@ -59,6 +61,8 @@ describe MigrateAutoDevOpsDomainToClusterDomain, :migration do
expect(cluster.domain).to be_present expect(cluster.domain).to be_present
end end
expect(clusters_without_domain.count).to eq(25)
project_auto_devops_without_domain.each do |project_auto_devops| project_auto_devops_without_domain.each do |project_auto_devops|
cluster_project = Clusters::Project.find_by(project_id: project_auto_devops.project_id) cluster_project = Clusters::Project.find_by(project_id: project_auto_devops.project_id)
cluster = Clusters::Cluster.find(cluster_project.cluster_id) cluster = Clusters::Cluster.find(cluster_project.cluster_id)
...@@ -74,10 +78,12 @@ describe MigrateAutoDevOpsDomainToClusterDomain, :migration do ...@@ -74,10 +78,12 @@ describe MigrateAutoDevOpsDomainToClusterDomain, :migration do
cluster_projects = cluster_projects_table.last(quantity) cluster_projects = cluster_projects_table.last(quantity)
cluster_projects.each do |cluster_project| cluster_projects.each do |cluster_project|
specific_domain = "#{cluster_project.id}-#{domain}" if domain
project_auto_devops_table.create( project_auto_devops_table.create(
project_id: cluster_project.project_id, project_id: cluster_project.project_id,
enabled: true, enabled: true,
domain: domain domain: specific_domain
) )
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment