Commit 80caa5c9 authored by Yorick Peterse's avatar Yorick Peterse

Add migration to fix a merge_requests index

In https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52116 we
introduced a new index used when generating changelogs using the GitLab
API. This migration failed in staging and production, but due to
https://github.com/lfittl/pg_query/issues/184 the original error is
masked, and an INVALID index is left behind.

This commit turns the old migration into a noop, and creates a new
migration. This new migration catches any CREATE INDEX errors and raises
a regular error, preventing the pg_query bug from surfacing. It also
removes the existing index if it's marked as INVALID. In addition, we
disable statement timeouts when creating the index; something we forgot
to do in the previous migration.
parent b4b17286
# frozen_string_literal: true
class AddOldestMergeRequestsIndex < ActiveRecord::Migration[6.0]
include Gitlab::Database::SchemaHelpers
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
INDEX = 'index_on_merge_requests_for_latest_diffs'
def up
return if index_exists_by_name?('merge_requests', INDEX)
execute "CREATE INDEX CONCURRENTLY #{INDEX} ON merge_requests " \
'USING btree (target_project_id) INCLUDE (id, latest_merge_request_diff_id)'
create_comment(
'INDEX',
INDEX,
'Index used to efficiently obtain the oldest merge request for a commit SHA'
)
# replaced by db/migrate/20210201140434_add_oldest_merge_requests_index_again.rb
end
def down
return unless index_exists_by_name?('merge_requests', INDEX)
execute "DROP INDEX CONCURRENTLY #{INDEX}"
# replaced by db/migrate/20210201140434_add_oldest_merge_requests_index_again.rb
end
end
# frozen_string_literal: true
class AddOldestMergeRequestsIndexAgain < ActiveRecord::Migration[6.0]
include Gitlab::Database::SchemaHelpers
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
DOWNTIME = false
INDEX = 'index_on_merge_requests_for_latest_diffs'
def up
execute "DROP INDEX CONCURRENTLY #{INDEX}" if invalid_index?
return if index_exists_by_name?('merge_requests', INDEX)
begin
disable_statement_timeout do
execute "CREATE INDEX CONCURRENTLY #{INDEX} ON merge_requests " \
'USING btree (target_project_id) INCLUDE (id, latest_merge_request_diff_id)'
end
rescue ActiveRecord::StatementInvalid => ex
# Due to https://github.com/lfittl/pg_query/issues/184, if the CREATE
# INDEX statement fails, we trigger a separate error due to the Gem not
# supporting the INCLUDE syntax.
#
# To work around this, we raise a custom error instead, as these won't
# have a query context injected.
raise "The index #{INDEX} couldn't be added: #{ex.message}"
end
create_comment(
'INDEX',
INDEX,
'Index used to efficiently obtain the oldest merge request for a commit SHA'
)
end
def down
return unless index_exists_by_name?('merge_requests', INDEX)
disable_statement_timeout do
execute "DROP INDEX CONCURRENTLY #{INDEX}"
end
end
def invalid_index?
result = execute(<<~SQL)
SELECT pg_class.relname
FROM pg_class, pg_index
WHERE pg_index.indisvalid = false
AND pg_index.indexrelid = pg_class.oid
AND pg_class.relname = '#{INDEX}';
SQL
result.values.any?
end
end
71220cfc36215f6c22d22d1fb0b74389e90c58733214b5fa36dcb8da0377a120
\ No newline at end of file
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