FEATURE: Allow pausing of restore before DB migration and uploads are restored (#30269)

This can be helpful if you need to fix problems in the DB before the DB gets migrated as well as before uploads are restored.
This commit is contained in:
Gerhard Schlager 2024-12-16 12:50:08 +01:00 committed by GitHub
parent 04ba5baec0
commit 6b3e28216c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 48 additions and 5 deletions

View File

@ -16,7 +16,7 @@ module BackupRestore
@current_db = current_db @current_db = current_db
end end
def restore(db_dump_path) def restore(db_dump_path, interactive = false)
BackupRestore.move_tables_between_schemas(MAIN_SCHEMA, BACKUP_SCHEMA) BackupRestore.move_tables_between_schemas(MAIN_SCHEMA, BACKUP_SCHEMA)
@db_dump_path = db_dump_path @db_dump_path = db_dump_path
@ -24,6 +24,7 @@ module BackupRestore
create_missing_discourse_functions create_missing_discourse_functions
restore_dump restore_dump
pause_before_migration if interactive
migrate_database migrate_database
reconnect_database reconnect_database
@ -136,6 +137,16 @@ module BackupRestore
].compact.join(" ") ].compact.join(" ")
end end
def pause_before_migration
puts ""
puts "Attention! Pausing restore before migrating database.".red.bold
puts "You can work on the restored database in a separate Rails console."
puts ""
puts "Press any key to continue with the restore.".bold
puts ""
STDIN.getch
end
def migrate_database def migrate_database
log "Migrating the database..." log "Migrating the database..."

View File

@ -1,5 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require "colored2"
module BackupRestore module BackupRestore
RestoreDisabledError = Class.new(RuntimeError) RestoreDisabledError = Class.new(RuntimeError)
FilenameMissingError = Class.new(RuntimeError) FilenameMissingError = Class.new(RuntimeError)
@ -9,12 +11,20 @@ module BackupRestore
attr_reader :success attr_reader :success
def initialize(user_id:, filename:, factory:, disable_emails: true, location: nil) def initialize(
user_id:,
filename:,
factory:,
disable_emails: true,
location: nil,
interactive: false
)
@user_id = user_id @user_id = user_id
@filename = filename @filename = filename
@factory = factory @factory = factory
@logger = factory.logger @logger = factory.logger
@disable_emails = disable_emails @disable_emails = disable_emails
@interactive = interactive
ensure_restore_is_enabled ensure_restore_is_enabled
ensure_we_have_a_user ensure_we_have_a_user
@ -48,7 +58,7 @@ module BackupRestore
@system.flush_redis @system.flush_redis
@system.clear_sidekiq_queues @system.clear_sidekiq_queues
@database_restorer.restore(db_dump_path) @database_restorer.restore(db_dump_path, @interactive)
reload_site_settings reload_site_settings
@ -58,7 +68,7 @@ module BackupRestore
clear_stats clear_stats
reload_translations reload_translations
@uploads_restorer.restore(@tmp_directory) restore_uploads
clear_emoji_cache clear_emoji_cache
clear_theme_cache clear_theme_cache
@ -143,6 +153,20 @@ module BackupRestore
TranslationOverride.reload_all_overrides! TranslationOverride.reload_all_overrides!
end end
def restore_uploads
if @interactive
puts ""
puts "Attention! Pausing restore before uploads.".red.bold
puts "You can work on the restored database in a separate Rails console."
puts ""
puts "Press any key to continue with the restore.".bold
puts ""
STDIN.getch
end
@uploads_restorer.restore(@tmp_directory)
end
def notify_user def notify_user
return if @success && @user_id == Discourse::SYSTEM_USER_ID return if @success && @user_id == Discourse::SYSTEM_USER_ID

View File

@ -154,7 +154,14 @@ class DiscourseCLI < Thor
end end
desc "restore", "Restore a Discourse backup" desc "restore", "Restore a Discourse backup"
option :disable_emails, type: :boolean, default: true option :disable_emails,
type: :boolean,
default: true,
desc: "Disable outgoing emails for non-staff users after restore"
option :pause,
type: :boolean,
default: false,
desc: "Pause before migrating database and restoring uploads"
option :location, type: :string, enum: %w[local s3], desc: "Override the backup location" option :location, type: :string, enum: %w[local s3], desc: "Override the backup location"
def restore(filename = nil) def restore(filename = nil)
load_rails load_rails
@ -179,6 +186,7 @@ class DiscourseCLI < Thor
disable_emails: options[:disable_emails], disable_emails: options[:disable_emails],
location: options[:location], location: options[:location],
factory: BackupRestore::Factory.new(user_id: Discourse.system_user.id), factory: BackupRestore::Factory.new(user_id: Discourse.system_user.id),
interactive: options[:pause],
) )
restorer.run restorer.run
puts "Restore done." puts "Restore done."