0
0
Fork 0

Fix null values being included in some indexes (#17711)

* Fix null values being included in some indexes

* Update lib/mastodon/migration_helpers.rb

Co-authored-by: Claire <claire.github-309c@sitedethib.com>

* Add documentation link to corruption error message

Co-authored-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
Eugen Rochko 2022-03-12 08:12:57 +01:00 committed by GitHub
parent bc320d6cec
commit 75e33fd08f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 354 additions and 37 deletions

View file

@ -42,8 +42,14 @@
module Mastodon
module MigrationHelpers
class CorruptionError < StandardError
def initialize(message = nil)
super(message.presence || 'Migration failed because of index corruption, see https://docs.joinmastodon.org/admin/troubleshooting/index-corruption/#fixing')
attr_reader :index_name
def initialize(index_name)
@index_name = index_name
super "The index `#{index_name}` seems to be corrupted, it contains duplicate rows. " \
'For information on how to fix this, see our documentation: ' \
'https://docs.joinmastodon.org/admin/troubleshooting/index-corruption/'
end
def cause
@ -802,6 +808,24 @@ module Mastodon
columns(table).find { |column| column.name == name }
end
# Update the configuration of an index by creating a new one and then
# removing the old one
def update_index(table_name, index_name, columns, **index_options)
if index_name_exists?(table_name, "#{index_name}_new") && index_name_exists?(table_name, index_name)
remove_index table_name, "#{index_name}_new"
end
begin
add_index table_name, columns, **index_options.merge(name: "#{index_name}_new", algorithm: :concurrently)
rescue ActiveRecord::RecordNotUnique
remove_index table_name, name: "#{index_name}_new"
raise CorruptionError.new(index_name)
end
remove_index table_name, name: index_name if index_name_exists?(table_name, index_name)
rename_index table_name, "#{index_name}_new", index_name
end
# This will replace the first occurrence of a string in a column with
# the replacement
# On postgresql we can use `regexp_replace` for that.

View file

@ -17,23 +17,10 @@ namespace :db do
end
end
task :post_migration_hook do
at_exit do
unless %w(C POSIX).include?(ActiveRecord::Base.connection.select_one('SELECT datcollate FROM pg_database WHERE datname = current_database();')['datcollate'])
warn <<~WARNING
Your database collation may be susceptible to index corruption.
(This warning does not indicate that index corruption has occurred, and it can be ignored if you've previously checked for index corruption)
(To learn more, visit: https://docs.joinmastodon.org/admin/troubleshooting/index-corruption/)
WARNING
end
end
end
task :pre_migration_check do
version = ActiveRecord::Base.connection.select_one("SELECT current_setting('server_version_num') AS v")['v'].to_i
abort 'ERROR: This version of Mastodon requires PostgreSQL 9.5 or newer. Please update PostgreSQL before updating Mastodon.' if version < 90_500
abort 'This version of Mastodon requires PostgreSQL 9.5 or newer. Please update PostgreSQL before updating Mastodon' if version < 90_500
end
Rake::Task['db:migrate'].enhance(['db:pre_migration_check'])
Rake::Task['db:migrate'].enhance(['db:post_migration_hook'])
end