Re-adding missing uploads to the database

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:

  1. Post con URL brevi upload:// (SHA1 codificato in base62).
  2. Database uploads che mappa SHA1 → percorso file locale.
  3. 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_all per 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.

3 Mi Piace