diff options
author | Shinya Maeda <shinya@gitlab.com> | 2018-07-30 10:11:43 +0900 |
---|---|---|
committer | Shinya Maeda <shinya@gitlab.com> | 2018-07-30 10:11:43 +0900 |
commit | 1f9992625ed8a954dde5b8e662e764c48598104d (patch) | |
tree | 07a4873d2de8dba00413175fa1bb994372e0e96b /db | |
parent | 8b3c7f57b249b087a36eb36588223d1c7c4dbafe (diff) | |
parent | 87f03f01735fb4b6dbef2e4bf625cf2546523a4e (diff) | |
download | gitlab-ce-1f9992625ed8a954dde5b8e662e764c48598104d.tar.gz |
Merge branch 'master-ce' into artifact-format-v2
Diffstat (limited to 'db')
-rw-r--r-- | db/migrate/20180702124358_remove_orphaned_routes.rb | 49 | ||||
-rw-r--r-- | db/migrate/20180702134423_generate_missing_routes.rb | 143 |
2 files changed, 192 insertions, 0 deletions
diff --git a/db/migrate/20180702124358_remove_orphaned_routes.rb b/db/migrate/20180702124358_remove_orphaned_routes.rb new file mode 100644 index 00000000000..6f6e289ba87 --- /dev/null +++ b/db/migrate/20180702124358_remove_orphaned_routes.rb @@ -0,0 +1,49 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class RemoveOrphanedRoutes < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + class Route < ActiveRecord::Base + self.table_name = 'routes' + include EachBatch + + def self.orphaned_namespace_routes + where(source_type: 'Namespace') + .where('NOT EXISTS ( SELECT 1 FROM namespaces WHERE namespaces.id = routes.source_id )') + end + + def self.orphaned_project_routes + where(source_type: 'Project') + .where('NOT EXISTS ( SELECT 1 FROM projects WHERE projects.id = routes.source_id )') + end + end + + def up + # Some of these queries can take up to 10 seconds to run on GitLab.com, + # which is pretty close to our 15 second statement timeout. To ensure a + # smooth deployment procedure we disable the statement timeouts for this + # migration, just in case. + disable_statement_timeout + + # On GitLab.com there are around 4000 orphaned project routes, and around + # 150 orphaned namespace routes. + [ + Route.orphaned_project_routes, + Route.orphaned_namespace_routes + ].each do |relation| + relation.each_batch(of: 1_000) do |batch| + batch.delete_all + end + end + end + + def down + # There is no way to restore orphaned routes, and this doesn't make any + # sense anyway. + end +end diff --git a/db/migrate/20180702134423_generate_missing_routes.rb b/db/migrate/20180702134423_generate_missing_routes.rb new file mode 100644 index 00000000000..994725f9bd1 --- /dev/null +++ b/db/migrate/20180702134423_generate_missing_routes.rb @@ -0,0 +1,143 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +# This migration generates missing routes for any projects and namespaces that +# don't already have a route. +# +# On GitLab.com this would insert 611 project routes, and 0 namespace routes. +# The exact number could vary per instance, so we take care of both just in +# case. +class GenerateMissingRoutes < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + class User < ActiveRecord::Base + self.table_name = 'users' + end + + class Route < ActiveRecord::Base + self.table_name = 'routes' + end + + module Routable + def build_full_path + if parent && path + parent.build_full_path + '/' + path + else + path + end + end + + def build_full_name + if parent && name + parent.human_name + ' / ' + name + else + name + end + end + + def human_name + build_full_name + end + + def attributes_for_insert + time = Time.zone.now + + { + # We can't use "self.class.name" here as that would include the + # migration namespace. + source_type: source_type_for_route, + source_id: id, + created_at: time, + updated_at: time, + name: build_full_name, + + # The route path might already be taken. Instead of trying to generate a + # new unique name on every conflict, we just append the row ID to the + # route path. + path: "#{build_full_path}-#{id}" + } + end + end + + class Project < ActiveRecord::Base + self.table_name = 'projects' + + include EachBatch + include GenerateMissingRoutes::Routable + + belongs_to :namespace, class_name: 'GenerateMissingRoutes::Namespace' + + has_one :route, + as: :source, + inverse_of: :source, + class_name: 'GenerateMissingRoutes::Route' + + alias_method :parent, :namespace + alias_attribute :parent_id, :namespace_id + + def self.without_routes + where( + 'NOT EXISTS ( + SELECT 1 + FROM routes + WHERE source_type = ? + AND source_id = projects.id + )', + 'Project' + ) + end + + def source_type_for_route + 'Project' + end + end + + class Namespace < ActiveRecord::Base + self.table_name = 'namespaces' + + include EachBatch + include GenerateMissingRoutes::Routable + + belongs_to :parent, class_name: 'GenerateMissingRoutes::Namespace' + belongs_to :owner, class_name: 'GenerateMissingRoutes::User' + + has_one :route, + as: :source, + inverse_of: :source, + class_name: 'GenerateMissingRoutes::Route' + + def self.without_routes + where( + 'NOT EXISTS ( + SELECT 1 + FROM routes + WHERE source_type = ? + AND source_id = namespaces.id + )', + 'Namespace' + ) + end + + def source_type_for_route + 'Namespace' + end + end + + def up + [Namespace, Project].each do |model| + model.without_routes.each_batch(of: 100) do |batch| + rows = batch.map(&:attributes_for_insert) + + Gitlab::Database.bulk_insert(:routes, rows) + end + end + end + + def down + # Removing routes we previously generated makes no sense. + end +end |