Okay, ich habe es mit Claude und viel Lob gelöst. Ich teile, was ich getan habe, um jedem mit einem ähnlichen oder demselben Problem zu helfen.
Ich bin mir nicht sicher, ob dies die cleverste und optimalste Methode ist, nur die, die für mich funktioniert hat.
Bitte seien Sie vorsichtig und denken Sie daran, dass ich kein Experte, sondern ein Anfänger bin, der immer lernt.
Das Problem (S3 → lokales Dateisystem)
Nach der Migration von AWS S3 auf das lokale Dateisystem wurden viele Bilder als transparent.png angezeigt. Die Dateien waren immer auf der Festplatte vorhanden, aber Discourse konnte sie nicht auflösen.
Die eigentliche Ursache war eine fehlerhafte Kette:
- Beiträge mit
upload://Kurz-URLs (base62-kodiertes SHA1). - Datenbank
uploads-Zuordnung SHA1 → lokaler Dateipfad. - Dateisystem, das Dateien speichert, die mit ihrem SHA1-Hash benannt sind.
Die Migration hat die Dateien korrekt auf die Festplatte verschoben, aber es gab keine uploads-DB-Einträge. Ohne einen passenden Eintrag fällt Discourse auf transparent.png zurück.
Die Lösung (Datensätze erstellen und erneut backen)
Fehlende Upload-Datensätze aus verwaisten Dateien erstellen:
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}"
Beiträge, die wiederhergestellte Uploads referenzieren, erneut backen:
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\s]+?(?=[ \]]|$)/) # Angepasst, um besser mit verschiedenen Trennzeichen umzugehen
urls.each do |url|
decoded = Upload.sha1_from_short_url(url.first) # scan gibt eine Array von Matches zurück
if decoded == u.sha1
p.rebake!
fixed_posts += 1
puts "Rebaked post #{p.id}"
break
end
end
end
end
puts "Total rebaked: #{fixed_posts}"
Fehlende optimierte Dateien neu generieren:
Nachdem die ursprünglichen Dateien korrigiert wurden, müssen wir die optimierten Dateien (1X, 2X usw.) auffüllen.
rake uploads:regenerate_missing_optimized
Sicheres Rollback (nur für den Fall)
Alle erstellten Datensätze verwenden user_id: -1. Zum Rückgängigmachen:
Upload.where(user_id: -1).delete_all
delete_all überspringt Rückrufe, sodass die Dateien im Dateisystem unberührt bleiben.
Zuvor wurde versehentlich
destroy_allverwendet, was Rückrufe auslöste, die Dateien in den Papierkorb verschoben haben.Ich habe eine einzelne Datei, die ich zum Testen verwendet habe, wiederhergestellt und meinen Ansatz neu formuliert.