Мы размещаем собственную базу данных Discourse и пытаемся перенести её на новый сервер.
Обе стороны (старая и новая) обновлены до последней версии Discourse (пересборка приложения на обеих сторонах была выполнена с разницей в несколько минут), а миграция на новый PostgreSQL на старом сервере успешно завершена несколько дней назад. Я бы исключил эти факторы как источник наших проблем.
Все наши загрузки хранятся в объектном хранилище, совместимом с S3 (Digitalocean Spaces), поэтому теоретически миграция должна быть простой. Я думал, что если часть восстановления «посты и категории» работает корректно, то ссылки на загрузки в S3 должны просто работать, верно?
Неправильно. Каждый раз, когда я выполняю восстановление нашей резервной копии на новом сервере, часть с постами проходит на 100% успешно, но затем процесс падает на этапе S3.
Вот ошибка, которую мы видим.
Reconnecting to the database...
Reloading site settings...
Disabling outgoing emails for non-staff users...
Running seed fu...
Disabling readonly mode...
Clearing category cache...
Reloading translations...
Remapping uploads...
Restoring uploads, this may take a while...
Migrating uploads to S3 for 'default'...
Uploading files to S3...
- Listing local files
=> 3 files
- Listing S3 files
..................................................................................................................................................... => 148892 files
- Syncing files to S3
...
Updating the URLs in the database...
Removing old optimized images...
Flagging all posts containing lightboxes for rebake...
29368 posts were flagged for a rebake
EXCEPTION: rake posts:missing_uploads identified 2274 issues. S3 migration failed for db 'default'.
/var/www/discourse/lib/file_store/to_s3_migration.rb:132:in 'FileStore::ToS3Migration#raise_or_log'
/var/www/discourse/lib/file_store/to_s3_migration.rb:104:in 'FileStore::ToS3Migration#migration_successful?'
/var/www/discourse/lib/file_store/to_s3_migration.rb:384:in 'FileStore::ToS3Migration#migrate_to_s3'
/var/www/discourse/lib/file_store/to_s3_migration.rb:59:in 'FileStore::ToS3Migration#migrate'
/var/www/discourse/lib/file_store/s3_store.rb:372:in 'FileStore::S3Store#copy_from'
/var/www/discourse/lib/backup_restore/uploads_restorer.rb:69:in 'BackupRestore::UploadsRestorer#restore_uploads'
/var/www/discourse/lib/backup_restore/uploads_restorer.rb:49:in 'BackupRestore::UploadsRestorer#restore'
/var/www/discourse/lib/backup_restore/restorer.rb:179:in 'BackupRestore::Restorer#restore_uploads'
/var/www/discourse/lib/backup_restore/restorer.rb:72:in 'BackupRestore::Restorer#run'
script/discourse:242:in 'DiscourseCLI#restore'
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/command.rb:28:in 'Thor::Command#run'
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/invocation.rb:127:in 'Thor::Invocation#invoke_command'
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor.rb:538:in 'Thor.dispatch'
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/base.rb:585:in 'Thor::Base::ClassMethods#start'
script/discourse:396:in '<top (required)>'
/usr/local/lib/ruby/gems/3.4.0/gems/bundler-4.0.11/lib/bundler/cli/exec.rb:61:in 'Kernel.load'
/usr/local/lib/ruby/gems/3.4.0/gems/bundler-4.0.11/lib/bundler/cli/exec.rb:61:in 'Bundler::CLI::Exec#kernel_load'
/usr/local/lib/ruby/gems/3.4.0/gems/bundler-4.0.11/lib/bundler/cli/exec.rb:24:in 'Bundler::CLI::Exec#run'
/usr/local/lib/ruby/gems/3.4.0/gems/bundler-4.0.11/lib/bundler/cli.rb:504:in 'Bundler::CLI#exec'
/usr/local/lib/ruby/gems/3.4.0/gems/bundler-4.0.11/lib/bundler/vendor/thor/lib/thor/command.rb:28:in 'Bundler::Thor::Command#run'
/usr/local/lib/ruby/gems/3.4.0/gems/bundler-4.0.11/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in 'Bundler::Thor::Invocation#invoke_command'
/usr/local/lib/ruby/gems/3.4.0/gems/bundler-4.0.11/lib/bundler/vendor/thor/lib/thor.rb:538:in 'Bundler::Thor.dispatch'
/usr/local/lib/ruby/gems/3.4.0/gems/bundler-4.0.11/lib/bundler/cli.rb:35:in 'Bundler::CLI.dispatch'
/usr/local/lib/ruby/gems/3.4.0/gems/bundler-4.0.11/lib/bundler/vendor/thor/lib/thor/base.rb:584:in 'Bundler::Thor::Base::ClassMethods#start'
/usr/local/lib/ruby/gems/3.4.0/gems/bundler-4.0.11/lib/bundler/cli.rb:29:in 'Bundler::CLI.start'
/usr/local/lib/ruby/gems/3.4.0/gems/bundler-4.0.11/exe/bundle:28:in 'block in <top (required)>'
/usr/local/lib/ruby/gems/3.4.0/gems/bundler-4.0.11/lib/bundler/friendly_errors.rb:118:in 'Bundler.with_friendly_errors'
/usr/local/lib/ruby/gems/3.4.0/gems/bundler-4.0.11/exe/bundle:20:in '<top (required)>'
/usr/local/bin/bundle:25:in 'Kernel#load'
/usr/local/bin/bundle:25:in '<main>'
Trying to rollback...
Rolling back...
Cleaning stuff up...
Dropping functions from the discourse_functions schema...
Removing tmp '/var/www/discourse/tmp/restores/default/2026-08-11-075958' directory...
Unpausing sidekiq...
Marking restore as finished...
Notifying 'system' of the end of the restore...
Finished!
[FAILED]
Restore done.
У меня есть несколько вопросов:
- почему процесс падает, если, по сути, настройки среды S3, сохранённые в базе данных, не изменились?
- почему он аварийно завершает работу, вместо того чтобы создать список из 2274 проблем с загрузками, которые я мог бы как-то обработать?
- почему он автоматически откатывает изменения к пустой базе данных, оставляя меня в подвешенном состоянии?
- Есть ли способ взять управление в свои руки, позволить ему успешно завершить восстановление или хотя бы не выполнять откат, чтобы я мог самостоятельно разобраться с обнаруженными проблемами загрузок?
Заранее большое спасибо за любую помощь!