Ok, l’ho risolto con Claude e molti complimenti. Condivido quello che ho fatto per aiutare chiunque abbia un problema simile o identico.
Non sono sicuro che questo sia il metodo più intelligente e ottimale da usare, ma è quello che ha funzionato per me.
Per favore, fate attenzione e tenete presente che non sono un esperto, ma un principiante che impara sempre.
Il problema (da S3 a filesystem locale)
Dopo la migrazione da AWS S3 a filesystem locale, molte immagini venivano visualizzate come transparent.png. I file erano sempre su disco, ma Discourse non riusciva a risolverli.
La causa principale era una catena interrotta:
- Post con URL brevi
upload://(SHA1 codificato in base62). - Database
uploadsche mappa SHA1 → percorso file locale. - Filesystem che memorizza i file denominati con il loro hash SHA1,
La migrazione ha spostato i file su disco correttamente, ma non esistevano record DB uploads. Senza un record corrispondente, Discourse ripiega su transparent.png.
La soluzione (creare record e ribake)
Creare record di caricamento mancanti dai file orfani:
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}"
Rifare il bake dei post che fanno riferimento ai caricamenti ripristinati:
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}"
Rigenerare gli ottimizzati mancanti:
Dopo aver corretto i file originali, dobbiamo popolare i file ottimizzati (1X, 2X, ecc.).
rake uploads:regenerate_missing_optimized
Rollback sicuro (giusto per ogni evenienza)
Tutti i record creati utilizzano user_id: -1. Per annullare:
Upload.where(user_id: -1).delete_all
delete_all salta i callback quindi i file del filesystem non vengono toccati.
In precedenza ho usato
destroy_allper errore e questo ha innescato i callback che hanno spostato i file nella cartella di rimozione (tombstone).Ne ho recuperato uno individuale che ho usato per testare e ho riformulato il mio approccio.