A restauração falha devido a erro na migração do S3

Nós hospedamos nosso próprio banco de dados Discourse e estamos tentando migrar para um novo servidor.

Ambos os lados (antigo e novo) foram atualizados para a versão mais recente do Discourse (uma reconstrução da aplicação em ambos os lados foi realizada com poucos minutos de diferença) e a migração para o novo PostgreSQL foi realizada com sucesso no servidor antigo alguns dias atrás. Eu descartaria essas questões como a origem dos nossos problemas.

Todos os nossos uploads estão armazenados em um armazenamento de objetos compatível com S3 (Digitalocean Spaces), então, no papel, a migração deveria ser fácil. Eu pensei que, se a parte de “posts e categorias” da restauração funcionasse bem, então os links para os uploads no S3 deveriam simplesmente funcionar, certo?

Errado. Sempre que eu executo a restauração do nosso backup no novo servidor, a parte dos posts vai 100% bem, mas então falha na parte do S3.

Este é o erro que vemos.

Reconectando ao banco de dados...
Recarregando configurações do site...
Desabilitando e-mails de saída para usuários não membros da equipe...
Executando seed fu...
Desabilitando modo somente leitura...
Limpando cache de categorias...
Recarregando traduções...
Remapeando uploads...
Restaurando uploads, isso pode levar algum tempo...
Migrando uploads para S3 para 'default'...
Enviando arquivos para S3...
 - Listando arquivos locais
 => 3 arquivos
 - Listando arquivos S3
..................................................................................................................................................... => 148892 arquivos
 - Sincronizando arquivos para S3
...
Atualizando as URLs no banco de dados...
Removendo imagens otimizadas antigas...
Marcando todos os posts contendo lightboxes para rebake...
29368 posts foram marcados para rebake
EXCEÇÃO: rake posts:missing_uploads identificou 2274 problemas. A migração S3 falhou para o banco de dados '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>'
Tentando rollback...
Realizando rollback...
Limpando...
Dropping funções do esquema discourse_functions...
Removendo diretório tmp '/var/www/discourse/tmp/restores/default/2026-08-11-075958'...
Despausando sidekiq...
Marcando restauração como finalizada...
Notificando 'system' do fim da restauração...
Finalizado!
[FALHOU]
Restauração concluída.

Tenho algumas perguntas:

  • por que está falhando quando, em princípio, a configuração do ambiente S3 que salvamos no banco de dados não foi alterada?
  • por que está travando, em vez de criar uma lista dos 2274 problemas que encontrou com os uploads que eu possa gerenciar de alguma forma?
  • por que está automaticamente fazendo rollback para um banco de dados vazio, deixando-me no meio do nada?
  • Existe uma maneira de eu assumir o controle, deixá-lo concluir a restauração com sucesso ou, pelo menos, não fazer rollback e me permitir lidar com os problemas que encontrou com os uploads?

Muito obrigado antecipadamente por qualquer ajuda!