mirror of
https://github.com/discourse/discourse.git
synced 2024-12-14 18:04:17 +08:00
f69dacf979
Simplified flow of restore is like that ``` migrate_database reconnect extract_uploads ``` Problem with incorrect current database started with this fix https://github.com/discourse/discourse/commit/025d4ee91f4 Dump task is reconnecting to default database https://github.com/rails/rails/blob/master/activerecord/lib/active_record/railties/databases.rake#L429 And then, we are trying to reconnect to the original database with that code: ``` def reconnect_database log "Reconnecting to the database..." RailsMultisite::ConnectionManagement::establish_connection(db: @current_db) end ``` This reconnect is not switching us back to correct database because of that check https://github.com/discourse/rails_multisite/blob/master/lib/rails_multisite/connection_management.rb#L181 Basically, it finds existing handler and it thinks that we are connected to correct DB and this step can be skipped. To solve it, we can reload RailsMultisite::ConnectionManagement which creates a new instance of that class https://github.com/discourse/rails_multisite/blob/master/lib/rails_multisite/connection_management.rb#L38
126 lines
3.9 KiB
Ruby
126 lines
3.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'rails_helper'
|
|
|
|
describe BackupRestore::Restorer do
|
|
it 'detects which pg_dump output is restorable to different schemas' do
|
|
{
|
|
"9.6.7" => true,
|
|
"9.6.8" => false,
|
|
"9.6.9" => false,
|
|
"10.2" => true,
|
|
"10.3" => false,
|
|
"10.3.1" => false,
|
|
"10.4" => false,
|
|
"11" => false,
|
|
"11.4" => false,
|
|
"21" => false,
|
|
}.each do |key, value|
|
|
expect(described_class.pg_produces_portable_dump?(key)).to eq(value)
|
|
end
|
|
end
|
|
|
|
describe 'Decompressing a backup' do
|
|
fab!(:admin) { Fabricate(:admin) }
|
|
|
|
before do
|
|
SiteSetting.allow_restore = true
|
|
@restore_path = File.join(Rails.root, "public", "backups", RailsMultisite::ConnectionManagement.current_db)
|
|
end
|
|
|
|
after do
|
|
FileUtils.rm_rf @restore_path
|
|
FileUtils.rm_rf @restorer.tmp_directory
|
|
end
|
|
|
|
context 'When there are uploads' do
|
|
before do
|
|
@restore_folder = "backup-#{SecureRandom.hex}"
|
|
@temp_folder = "#{@restore_path}/#{@restore_folder}"
|
|
FileUtils.mkdir_p("#{@temp_folder}/uploads")
|
|
|
|
Dir.chdir(@restore_path) do
|
|
File.write("#{@restore_folder}/dump.sql", 'This is a dump')
|
|
Compression::Gzip.new.compress(@restore_folder, 'dump.sql')
|
|
FileUtils.rm_rf("#{@restore_folder}/dump.sql")
|
|
File.write("#{@restore_folder}/uploads/upload.txt", 'This is an upload')
|
|
|
|
Compression::Tar.new.compress(@restore_path, @restore_folder)
|
|
end
|
|
|
|
Compression::Gzip.new.compress(@restore_path, "#{@restore_folder}.tar")
|
|
FileUtils.rm_rf @temp_folder
|
|
|
|
build_restorer("#{@restore_folder}.tar.gz")
|
|
end
|
|
|
|
it '#decompress_archive works correctly' do
|
|
@restorer.decompress_archive
|
|
|
|
expect(exists?("dump.sql.gz")).to eq(true)
|
|
expect(exists?("uploads", directory: true)).to eq(true)
|
|
end
|
|
|
|
it '#extract_dump works correctly' do
|
|
@restorer.decompress_archive
|
|
@restorer.extract_dump
|
|
|
|
expect(exists?('dump.sql')).to eq(true)
|
|
end
|
|
end
|
|
|
|
context 'When restoring a single file' do
|
|
before do
|
|
FileUtils.mkdir_p(@restore_path)
|
|
|
|
Dir.chdir(@restore_path) do
|
|
File.write('dump.sql', 'This is a dump')
|
|
Compression::Gzip.new.compress(@restore_path, 'dump.sql')
|
|
FileUtils.rm_rf('dump.sql')
|
|
end
|
|
|
|
build_restorer('dump.sql.gz')
|
|
end
|
|
|
|
it '#extract_dump works correctly with a single file' do
|
|
@restorer.extract_dump
|
|
|
|
expect(exists?("dump.sql")).to eq(true)
|
|
end
|
|
end
|
|
|
|
def exists?(relative_path, directory: false)
|
|
full_path = "#{@restorer.tmp_directory}/#{relative_path}"
|
|
directory ? File.directory?(full_path) : File.exists?(full_path)
|
|
end
|
|
|
|
def build_restorer(filename)
|
|
@restorer = described_class.new(admin.id, filename: filename)
|
|
@restorer.ensure_directory_exists(@restorer.tmp_directory)
|
|
@restorer.copy_archive_to_tmp_directory
|
|
end
|
|
end
|
|
|
|
context 'Database connection' do
|
|
fab!(:admin) { Fabricate(:admin) }
|
|
before do
|
|
SiteSetting.allow_restore = true
|
|
@restore_path = File.join(Rails.root, 'public', 'backups', RailsMultisite::ConnectionManagement.current_db)
|
|
described_class.any_instance.stubs(ensure_we_have_a_filename: true)
|
|
described_class.any_instance.stubs(initialize_state: true)
|
|
end
|
|
let(:conn) { RailsMultisite::ConnectionManagement }
|
|
let(:restorer) { described_class.new(admin.id) }
|
|
|
|
it 'correctly reconnects to database' do
|
|
restorer.instance_variable_set(:@current_db, 'second')
|
|
conn.config_filename = "spec/fixtures/multisite/two_dbs.yml"
|
|
conn.establish_connection(db: 'second')
|
|
expect(RailsMultisite::ConnectionManagement.current_db).to eq('second')
|
|
ActiveRecord::Base.connection_pool.spec.config[:db_key] = "incorrect_db"
|
|
restorer.send(:reconnect_database)
|
|
expect(RailsMultisite::ConnectionManagement.current_db).to eq('second')
|
|
end
|
|
end
|
|
end
|