Commit 650567e0 authored by Andreas Brandl's avatar Andreas Brandl

Simplify migration and use plain SQL

parent 9e273eae
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
class FixProjectsWithoutProjectFeature < ActiveRecord::Migration[5.2] class FixProjectsWithoutProjectFeature < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers include Gitlab::Database::MigrationHelpers
BATCH_SIZE = 100_000 BATCH_SIZE = 50_000
disable_ddl_transaction! disable_ddl_transaction!
......
...@@ -2,61 +2,59 @@ ...@@ -2,61 +2,59 @@
module Gitlab module Gitlab
module BackgroundMigration module BackgroundMigration
# Project model for this migration
class Project < ActiveRecord::Base
include EachBatch
end
ENABLED = 20
INSERT_BATCH_SIZE = 10_000
# This migration creates missing project_features records # This migration creates missing project_features records
# for the projects within the given range of ids # for the projects within the given range of ids
class FixProjectsWithoutProjectFeature class FixProjectsWithoutProjectFeature
def perform(from_id, to_id) def perform(from_id, to_id)
Project.transaction do if number_of_created_records = create_missing!(from_id, to_id) > 0
projects = Project.where(<<~SQL, from_id, to_id) log(number_of_created_records, from_id, to_id)
projects.id BETWEEN ? AND ?
AND NOT EXISTS (
SELECT 1 FROM project_features
WHERE project_features.project_id = projects.id
)
SQL
projects.each_batch(of: INSERT_BATCH_SIZE) do |batch|
insert_missing_records(batch)
end
end end
end end
private private
def insert_missing_records(projects) def create_missing!(from_id, to_id)
features = projects.map do |project| result = ActiveRecord::Base.connection.select_one(sql, nil, [[nil, from_id], [nil, to_id]])
record = { return 0 unless result
project_id: project.id,
merge_requests_access_level: ENABLED, result['number_of_created_records']
issues_access_level: ENABLED, end
wiki_access_level: ENABLED,
snippets_access_level: ENABLED, def sql
builds_access_level: ENABLED, <<~SQL
repository_access_level: ENABLED, WITH created_records AS (
pages_access_level: ENABLED, INSERT INTO project_features (
forking_access_level: ENABLED project_id,
} merge_requests_access_level,
issues_access_level,
record['created_at'] = record['updated_at'] = Time.now.to_s(:db) wiki_access_level,
snippets_access_level,
record builds_access_level,
repository_access_level,
pages_access_level,
forking_access_level,
created_at,
updated_at
)
SELECT projects.id, 20, 20, 20, 20, 20, 20, 20, 20, NOW(), NOW()
FROM projects
WHERE projects.id BETWEEN $1 AND $2
AND NOT EXISTS (
SELECT 1 FROM project_features
WHERE project_features.project_id = projects.id
)
ON CONFLICT (project_id) DO NOTHING
RETURNING *
)
SELECT COUNT(*) as number_of_created_records
FROM created_records
SQL
end end
Gitlab::Database.bulk_insert(:project_features, features, on_conflict: :do_nothing) def log(count, from_id, to_id)
logger = Gitlab::BackgroundMigration::Logger.build
logger.info(message: "FixProjectsWithoutProjectFeature: created missing project_features for Projects #{projects.map(&:id).join(', ')}")
end
def logger logger.info(message: "FixProjectsWithoutProjectFeature: created missing project_features for #{count} projects in id=#{from_id}...#{to_id}")
@logger ||= Gitlab::BackgroundMigration::Logger.build
end end
end end
end end
......
...@@ -25,10 +25,30 @@ describe Gitlab::BackgroundMigration::FixProjectsWithoutProjectFeature, :migrati ...@@ -25,10 +25,30 @@ describe Gitlab::BackgroundMigration::FixProjectsWithoutProjectFeature, :migrati
ActiveRecord::Base.connection.select_one('SELECT MIN(id), MAX(id) FROM projects').values ActiveRecord::Base.connection.select_one('SELECT MIN(id), MAX(id) FROM projects').values
end end
it 'creates a default ProjectFeature for projects without it' do it 'creates a ProjectFeature for projects without it' do
expect { subject }.to change { project_feature_records }.from([project.id]).to([project.id, *projects_without_feature.map(&:id)]) expect { subject }.to change { project_feature_records }.from([project.id]).to([project.id, *projects_without_feature.map(&:id)])
end end
it 'creates ProjectFeature records with default values' do
subject
project_id = projects_without_feature.first.id
record = ActiveRecord::Base.connection.select_one('SELECT * FROM project_features WHERE id=$1', nil, [[nil, project_id]])
expect(record.except('id', 'project_id', 'created_at', 'updated_at')).to eq(
{
"merge_requests_access_level" => 20,
"issues_access_level" => 20,
"wiki_access_level" => 20,
"snippets_access_level" => 20,
"builds_access_level" => 20,
"repository_access_level" => 20,
"pages_access_level" => 20,
"forking_access_level" => 20
}
)
end
it 'sets created_at/updated_at timestamps' do it 'sets created_at/updated_at timestamps' do
subject subject
......
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