Ok, eu resolvi com o Claude e muitos elogios. Estou compartilhando o que fiz para ajudar qualquer outra pessoa com um problema semelhante ou o mesmo.
Não tenho certeza se este é o método mais inteligente e otimizado a ser usado, apenas o que funcionou para mim.
Por favor, tenha cuidado e tenha em mente que não sou um especialista, mas um novato sempre aprendendo.
O problema (S3 → sistema de arquivos local)
Após a migração do AWS S3 para o sistema de arquivos local, muitas imagens eram exibidas como transparent.png. Os arquivos estavam sempre no disco, mas o Discourse não conseguia resolvê-los.
A causa raiz era uma cadeia quebrada:
- Posts com URLs curtas
upload://(SHA1 codificado em base62). - Banco de dados
uploadsmapeando SHA1 → caminho do arquivo local. - Sistema de arquivos armazenando arquivos nomeados pelo seu hash SHA1,
A migração moveu os arquivos para o disco corretamente, mas não havia registros de DB uploads. Sem um registro correspondente, o Discourse recorre ao transparent.png.
A solução (criar registros e reprocessar)
Criar registros de upload ausentes a partir de arquivos órfãos:
dir = Rails.root.join("public", "uploads", "default", "original")
created = 0
Dir.glob(dir.join("**", "*")).select { |f| File.file?(f) }.each do |path|
sha = File.basename(path, File.extname(path))
next if Upload.find_by(sha1: sha)
ext = File.extname(path).delete(".")
relative = path.sub("#{Rails.root}/public", "")
u = Upload.new
u.sha1 = sha
u.url = relative
u.original_filename = File.basename(path)
u.filesize = File.size(path)
u.extension = ext
u.user_id = -1
u.save!(validate: false)
created += 1
puts "Created upload #{u.id}: #{sha}"
end
puts "Total created: #{created}"
Reprocessar posts que referenciam uploads restaurados:
fixed_posts = 0
Upload.where(user_id: -1).find_each do |u|
short = u.short_url
next unless short
Post.where("raw LIKE '%upload://%'").find_each do |p|
urls = p.raw.scan(/upload:\/\/\[^\s\]\)]+/)
urls.each do |url|
decoded = Upload.sha1_from_short_url(url)
if decoded == u.sha1
p.rebake!
fixed_posts += 1
puts "Rebaked post #{p.id}"
break
end
end
end
end
puts "Total rebaked: #{fixed_posts}"
Regenerar otimizados ausentes:
Após corrigir os arquivos originais, precisamos preencher os arquivos otimizados (1X, 2X, etc.).
rake uploads:regenerate_missing_optimized
Rollback seguro (só por precaução)
Todos os registros criados usam user_id: -1. Para desfazer:
Upload.where(user_id: -1).delete_all
delete_all ignora os callbacks, então os arquivos do sistema de arquivos não são afetados.
Anteriormente, usei
destroy_allpor engano e isso acionou callbacks que moveram os arquivos para a lixeira.Recuperei um individual que usei para testar e reformulei minha abordagem.