Multisite restores uploads to 'default' instead of actual db name

On Discourse latest beta, docker install, multisite.

Trying to restore a backup with original database REDACTED to current database db8015. Uploads end up in default, both on filesystem and in database.

This happens both when the restore is triggered from the GUI, and when the restore is done on the command line using RAILS_DB=db8015 RAILS_ENV=production script/discourse restore.

During the restore process, RailsMultisite::ConnectionManagement.current_db changes from the correct database to default. I have been able to pin this down to [Rake::Task['db:_dump'].invoke in db.rake](discourse/lib/tasks/db.rake at master · discourse/discourse · GitHub). )

Before that line, RailsMultisite::ConnectionManagement.current_db has the correct value (db8015), after that line, it is default.

Looks like this fix has broken production somehow @sam?

Logs:

[STARTED]
'DHSupport' has started the restore!
Marking restore as running...
Making sure /var/www/discourse/tmp/restores/db8015/2019-10-11-104940 exists...
Copying archive to tmp directory...
Unzipping archive, this may take a while...
No metadata file to extract.
Validating metadata...
  Current version: 20191007140446
  Restored version: 20190908234054
Extracting dump file...
Creating missing functions in the discourse_functions schema
Cannot restore into different schema, restoring in-place
Enabling readonly mode...
Pausing sidekiq...

[deleted a lot of irrelevant stuff]

Clear theme cache
Extracting uploads...
Remapping uploads...
Remapping 'uploads/REDACTED' to 'uploads/default'
Optimizing site icons...
Posts will be rebaked by a background job in sidekiq. You will see missing images until that has completed.
You can expedite the process by manually running "rake posts:rebake_uncooked_posts"
Executing the after_restore_hook...
Cleaning stuff up...
Dropping function from the discourse_functions schema
Removing tmp '/var/www/discourse/tmp/restores/db8015/2019-10-11-104940' directory...
Unpausing sidekiq...
Marking restore as finished...
3 Likes

Is this still a problem @sam?

Just to clarify, repro is:

  • Create a multisite in a docker container

  • Backup one of the multisites

  • In a new docker container restore it

  • Uploads are in the wrong place

@kris.kotlarek can you repro this on local and see if you can fix it?

I suspect we will be hit by this in future.

3 Likes

Only the destination container needs to be multisite to repro this.

  • Create a forum in a docker container
  • Create a backup
  • In a new multisite docker container restore it
  • Uploads are in the wrong place
4 Likes

I spent some time on this bug, and I wanted to update you with my findings. Basically, I confirmed everything you already said, the restore process is like that:

migrate_database
reconnect_database
...
extract_uploads

Problem is that after the migration task, reconnect_database is not switching to the desired one, but starts working on default.

Therefore this code is wrong

def extract_uploads
  ...
  current_db_name = 
  RailsMultisite::ConnectionManagement.current_db # default
  optimized_images_exist = File.exist?(File.join(tmp_uploads_path, 'optimized'))

A hacky solution would be to use here @current_db which still contains correct name instead of RailsMultisite::ConnectionManagement.current_db but this is not solving real issue why reconnect database is not working properly.

I need to dig deeper to find the problem.

5 Likes

Are you sure that it is happening after the migration task?

This code

  migrate_database
  puts "After migrate, before reconnect #{RailsMultisite::ConnectionManagement.current_db}"
  reconnect_database

outputs this

Optimizing site icons... Done
After migrate, before reconnect default
Reconnecting to the database...

But when I comment out the line

Rake::Task['db:_dump'].invoke

in lib/tasks/db.rake

It outputs

Optimizing site icons... Done
After migrate, before reconnect db8015
Reconnecting to the database...
3 Likes

You are right. I removed Rake::Task["db:migrate"].invoke from restorer.rb and got correct database through the whole process.
You are one step ahead of me, my plan now is to go into migrate task and see which step is breaking process.
Thank you for pointing _dump, I will go directly there to see what is happening inside

4 Likes

I spent some time investigating that but finally I got a fix :slight_smile:

8 Likes

Thanks!

After giving this some more thought, what does it even mean when db:dump is ran on something which is not the primary database?

Shouldn’t it just skip the db:dump command if database is not default?

1 Like

Fixed was merged, thank you for finding that issue. That dump command was added because there was a problem with multisite migrations. I think that It shouldn’t matter which database we are using to dump structure because all multisites should have same structure.

5 Likes