From d8be981466e2a794b42996960f1fdb91e560a707 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 17 Nov 2017 13:38:14 +0000 Subject: Prevent update_column_in_batches on large tables add_column_with_default is implemented in terms of update_column_in_batches, but update_column_in_batches can be used independently. Neither of these should be used on the specified large tables, because they will cause issues on large instances like GitLab.com. This also ignores the cop for all existing migrations, renaming AddColumnWithDefaultToLargeTable where appropriate. --- .../add_column_with_default_to_large_table.rb | 55 --------------------- rubocop/cop/migration/update_large_table.rb | 57 ++++++++++++++++++++++ 2 files changed, 57 insertions(+), 55 deletions(-) delete mode 100644 rubocop/cop/migration/add_column_with_default_to_large_table.rb create mode 100644 rubocop/cop/migration/update_large_table.rb (limited to 'rubocop/cop') diff --git a/rubocop/cop/migration/add_column_with_default_to_large_table.rb b/rubocop/cop/migration/add_column_with_default_to_large_table.rb deleted file mode 100644 index fb363f95b56..00000000000 --- a/rubocop/cop/migration/add_column_with_default_to_large_table.rb +++ /dev/null @@ -1,55 +0,0 @@ -require_relative '../../migration_helpers' - -module RuboCop - module Cop - module Migration - # This cop checks for `add_column_with_default` on a table that's been - # explicitly blacklisted because of its size. - # - # Even though this helper performs the update in batches to avoid - # downtime, using it with tables with millions of rows still causes a - # significant delay in the deploy process and is best avoided. - # - # See https://gitlab.com/gitlab-com/infrastructure/issues/1602 for more - # information. - class AddColumnWithDefaultToLargeTable < RuboCop::Cop::Cop - include MigrationHelpers - - MSG = 'Using `add_column_with_default` on the `%s` table will take a ' \ - 'long time to complete, and should be avoided unless absolutely ' \ - 'necessary'.freeze - - LARGE_TABLES = %i[ - ci_pipelines - ci_builds - events - issues - merge_request_diff_files - merge_request_diffs - merge_requests - namespaces - notes - projects - routes - users - ].freeze - - def_node_matcher :add_column_with_default?, <<~PATTERN - (send nil :add_column_with_default $(sym ...) ...) - PATTERN - - def on_send(node) - return unless in_migration?(node) - - matched = add_column_with_default?(node) - return unless matched - - table = matched.to_a.first - return unless LARGE_TABLES.include?(table) - - add_offense(node, :expression, format(MSG, table)) - end - end - end - end -end diff --git a/rubocop/cop/migration/update_large_table.rb b/rubocop/cop/migration/update_large_table.rb new file mode 100644 index 00000000000..3ae3fb1b68e --- /dev/null +++ b/rubocop/cop/migration/update_large_table.rb @@ -0,0 +1,57 @@ +require_relative '../../migration_helpers' + +module RuboCop + module Cop + module Migration + # This cop checks for `add_column_with_default` on a table that's been + # explicitly blacklisted because of its size. + # + # Even though this helper performs the update in batches to avoid + # downtime, using it with tables with millions of rows still causes a + # significant delay in the deploy process and is best avoided. + # + # See https://gitlab.com/gitlab-com/infrastructure/issues/1602 for more + # information. + class UpdateLargeTable < RuboCop::Cop::Cop + include MigrationHelpers + + MSG = 'Using `%s` on the `%s` table will take a long time to ' \ + 'complete, and should be avoided unless absolutely ' \ + 'necessary'.freeze + + LARGE_TABLES = %i[ + ci_pipelines + ci_builds + events + issues + merge_request_diff_files + merge_request_diffs + merge_requests + namespaces + notes + projects + routes + users + ].freeze + + def_node_matcher :batch_update?, <<~PATTERN + (send nil ${:add_column_with_default :update_column_in_batches} $(sym ...) ...) + PATTERN + + def on_send(node) + return unless in_migration?(node) + + matches = batch_update?(node) + return unless matches + + update_method = matches.first + table = matches.last.to_a.first + + return unless LARGE_TABLES.include?(table) + + add_offense(node, :expression, format(MSG, update_method, table)) + end + end + end + end +end -- cgit v1.2.3