Generating missing optimized images with S3

After our migration (back) to Amazon S3, we appear to have quite a few images where the optimized versions are missing, but the full-size ones are there (example).

There is a Rake task for regenerating optimized images, but it only appears to work with local storage. How would I do this with remote images?

2 „Gefällt mir“

A question for @zogstrip I think!

Still waiting for an update on this.

We have some quite noticeable missing post images, and had at least one broken scaled avatar…

1 „Gefällt mir“

I’m afraid you’ll have to write your own rake task for that. Here’s some pseudo code on how I’d start

FOR EACH oi IN optimized_images
   IF file_exists_on_s3?(oi.upload.url) AND NOT file_exists_on_s3?(oi.url) THEN
       OptimizedImage.create_for(oi.upload, oi.width, oi.height)
   END IF 
END FOR
1 „Gefällt mir“

@uppfinnarn Did you manage to solve this?

I just migrated to S3, and indeed the /optimized/ folder is not transferred in the migration. I’d like to get rid of the /optimized/ folder, as it adds significant weight to my daily backup.

I’m not sure if the following is complete, but this rails console command removes all optimized images then regenerates the ones used for avatars:

OptimizedImage.destroy_all
UserAvatar.all.each {|ua| uaid = ua.gravatar_upload_id || ua.custom_upload_id; Jobs::CreateAvatarThumbnails.perform_async(upload_id: uaid) if uaid }
4 „Gefällt mir“

As a followup to the above command, doing a rake posts:rebake will regenerate all(?) of the other missing optimized images.

4 „Gefällt mir“

Team, ich habe mich in einer Situation im Zusammenhang mit dem Profilbild festgefahren, die mich etwa 6 Stunden gekostet hat :(, aber ich habe die perfekte Lösung gefunden und teile sie hier.

SPEICHERUNG: Nutzung von AWS S3 mit CDN davor.

Problem 1: Ich konnte das Profilbild im Bereich „Profilbild ändern“ hochladen, es wurde jedoch nicht im Profil angezeigt. Ich habe meinen Code auf die neueste Version von Discourse aktualisiert, und das Profilbild wird nun in der Benutzeroberfläche angezeigt :slight_smile:

ALTER CODE – Profilbild wurde nicht angezeigt


module FileStore

  class S3Store < BaseStore
     ...
    def path_for(upload)
      url = upload&.url
      if url && url[/^\/[^\/]/]
        FileStore::LocalStore.new.path_for(upload)
      else
        url
      end
    end
     ...
  end
end

LÖSUNG: NEUESTE VERSION – Profilbild wird bei neuen Uploads angezeigt

module FileStore

  class S3Store < BaseStore
     ...
    def path_for(upload)
      url = upload&.url
      FileStore::LocalStore.new.path_for(upload) if url && url[/^\/[^\/]/]
    end
     ...
  end
end

Hinweis: Bitte aktualisiert euren eigenen Code regelmäßig mit dem Discourse Upstream. Dadurch bleibt euer Code mit Sicherheitskorrekturen aktuell und fehlerfrei.

Problem 2: Mein Team und ich haben versucht, Profilbilder zu ändern, bevor wir den oben genannten Fehler in Problem 1 behoben haben. Dadurch entstanden viele Einträge in der Tabelle uploads mit dem Wert unknown in der Spalte extension. Der Code konnte das Profilbild im Prozess der Bildoptimierung (MODELL: OptimizedImage) aufgrund eines falschen S3-Dateipfads nicht korrekt verarbeiten.

Daher habe ich auch einen Workaround gefunden, um diese Art von Einträgen zu beheben, die vor meiner Codekorrektur entstanden sind.

Lösung

Multi-Site
Wir können den folgenden Code direkt in der Produktions-Rails-Konsole ausführen – oder über eine Rake-Aufgabe.

RailsMultisite::ConnectionManagement.each_connection do |db|
  Upload.where(extension: "unknown").each do |upload|
    upload.update(extension: File.extname(upload.url).gsub(".",""))
  end
  OptimizedImage.destroy_all
  UserAvatar.all.each {|ua| uaid = ua.gravatar_upload_id || ua.custom_upload_id; 
  Jobs::CreateAvatarThumbnails.perform_async(upload_id: uaid) if uaid }
end

Normal – Single Site
Wir können den folgenden Code direkt in der Produktions-Rails-Konsole ausführen – oder über eine Rake-Aufgabe.

Upload.where(extension: "unknown").each do |upload|
  upload.update(extension: File.extname(upload.url).gsub(".",""))
end
OptimizedImage.destroy_all
UserAvatar.all.each {|ua| uaid = ua.gravatar_upload_id || ua.custom_upload_id; 
Jobs::CreateAvatarThumbnails.perform_async(upload_id: uaid) if uaid }

Ich denke, das wird vielen Leuten helfen :slight_smile:

Vielen Dank

2 „Gefällt mir“

@supermathie Danke für deinen Rat. Wenn es so aussieht, als wären alle optimierten Bilder für Avatare fehlend, wäre es dann wahrscheinlich ausreichend, einfach die zweite Zeile auszuführen?

UserAvatar.all.each {|ua| uaid = ua.gravatar_upload_id || ua.custom_upload_id; Jobs::CreateAvatarThumbnails.perform_async(upload_id: uaid) if uaid }

Ich habe bereits ein Neuaufbereiten der Beiträge durchgeführt, was ziemlich lange gedauert hat. Daher möchte ich idealerweise vermeiden, die vorhandenen optimierten Dateien für Beitragsbilder zu löschen, falls möglich.

2 „Gefällt mir“

wahrscheinlich, aber es ist sehr gut möglich, dass sich der Code geändert hat; ich habe das schon eine Weile nicht mehr angesehen.

Ich werde mich mal umhören…

1 „Gefällt mir“

Danke @supermathie, ich schätze das! :slight_smile:

Also habe ich es einfach ausprobiert (nur die zweite Zeile), aber es scheint nicht zu funktionieren. Es wurden viele Datensätze zurückgegeben, wie zum Beispiel:

id: 1234,
user_id: 1234,
custom_upload_id: nil,
gravatar_upload_id: nil,
last_gravatar_download_attempt: Thu, 07 May 2015 09:40:35 UTC +00:00,
created_at: Thu, 07 May 2015 09:40:35 UTC +00:00,
updated_at: Thu, 07 May 2015 09:40:36 UTC +00:00>,

Ich habe einen Datensatz gefunden, bei dem custom_upload_id auf eine ID gesetzt war, und das Benutzerprofil mit User.find_by(id: 123456) abgerufen.

Beim Anzeigen des Profils ist das Avatar-Bild jedoch immer noch leer. Außerdem sehe ich, dass in den letzten 6 Stunden keine neuen Uploads nach S3 erfolgt sind. Daher gehe ich davon aus, dass keine optimierten Bilder als Ergebnis generiert werden.


Die gute Nachricht ist: Wenn ich über einen Rails-Befehl nach einem Avatar suche:

User.find_by_username('username').uploaded_avatar

source

scheinen die Datensätze korrekt zu sein, und die URLs für alle bisher geprüften S3-Links funktionieren. Die Datensätze stimmen mit einer anderen Instanz überein, die von Anfang an S3 genutzt hat.

Wenn ich dann folgendes verwende:
OptimizedImage.where(upload_id: upload_id).where(version: 2)

sehe ich in der vorherigen Instanz eine Reihe optimierter Bilder. In der neuen Instanz gibt es jedoch keine Datensätze. Das scheint korrekt zu sein. Für den Benutzer mit der gesetzten custom_upload_id scheinen zwar optimierte Bilder auf S3 vorhanden zu sein, aber diese Datensätze stammen jedoch von vor einigen Tagen.

Es scheint also, dass ich nur einen Weg finden muss, um die Generierung der optimierten Avatar-Bilder auszulösen.

Die neue Instanz befindet sich derzeit im Nur-Lese-Modus. Vielleicht ist das ein Faktor. Das Neuberechnen von Beiträgen funktionierte im Nur-Lese-Modus jedoch problemlos.


Edit: Ich sehe viele Jobs in Sidekiq zum Erstellen von Avatar-Thumbnail-Bildern :slight_smile:

Vielleicht muss ich nur den Nur-Lese-Modus verlassen, damit sie verarbeitet werden können. Ich werde mich dazu noch einmal melden.

Also ich sehe, dass Jobs::CreateAvatarThumbnails in Sidekiq ausgeführt wird. Aber seit 9 Stunden wurde nichts in den S3-Bucket hochgeladen. Daher bin ich mir nicht sicher, was ich davon halten soll.