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 « J'aime »

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 « J'aime »

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 « J'aime »

@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 « J'aime »

En complément de la commande ci-dessus, exécuter rake posts:rebake régénérera tous (ou presque) les autres images optimisées manquantes.

4 « J'aime »

Équipe, je me suis retrouvé bloqué dans une situation liée à l’image de profil, ce qui m’a fait perdre environ 6 heures :frowning: mais j’ai trouvé la solution parfaite, alors je la partage ici.

STOCKAGE : Utilisation d’AWS S3 avec un CDN en façade.

Problème 1 : J’ai pu télécharger l’image de profil depuis la zone de modification de l’image de profil, mais elle ne s’affichait pas dans le profil. J’ai mis à jour mon code vers la dernière version de Discourse et l’image de profil a commencé à s’afficher dans l’interface :slight_smile:

ANCIEN CODE - L’image de profil ne s’affichait pas

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

SOLUTION : DERNIER CODE - L’image de profil s’affiche maintenant pour les nouveaux téléchargements

module FileStore

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

Remarque : Veuillez, s’il vous plaît, continuer à mettre à jour votre propre code avec la version amont de Discourse régulièrement. Cela permettra de maintenir votre code à jour avec les correctifs de sécurité et sans bogues.

Problème 2 : Mon équipe et moi avons essayé de changer les images de profil avant de corriger le bogue mentionné ci-dessus dans le Problème 1. Cela a créé de nombreuses entrées dans la table uploads avec unknown comme valeur dans la colonne extension. Le code ne traitait pas correctement l’image de profil lors du processus d’optimisation des images (MODÈLE : OptimizedImage) en raison d’un chemin de fichier S3 incorrect.

J’ai donc également trouvé une solution de contournement pour corriger ce type d’entrées qui ont été créées avant ma correction de code.

Solution

Multi-Sites
Nous pouvons exécuter le code ci-dessous directement dans la console Rails de production, ou via une tâche rake.

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 - Site Unique
Nous pouvons exécuter le code ci-dessous directement dans la console Rails de production, ou via une tâche rake.

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 }

Je pense que cela aidera beaucoup de gens :slight_smile:

Merci

2 « J'aime »

@supermathie Merci pour vos conseils. S’il semble que toutes les images optimisées pour les avatars manquent, est-ce que simplement exécuter la deuxième ligne serait probablement suffisant ?

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

J’ai déjà effectué un rebake des posts, ce qui a pris pas mal de temps. J’aimerais donc idéalement éviter de supprimer les fichiers optimisés existants pour les images des posts si possible.

2 « J'aime »

probablement, mais il est tout à fait possible que le code ait changé ; je ne l’ai pas regardé depuis un moment.

Je vais me renseigner…

1 « J'aime »

Merci @supermathie, je l’apprécie ! :slight_smile:

J’ai donc essayé (juste la deuxième ligne), mais cela ne semble pas fonctionner. Cela a retourné beaucoup d’enregistrements comme :

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>,

J’en ai trouvé un avec custom_upload_id défini sur un ID et j’ai récupéré le profil de l’utilisateur en utilisant : User.find_by(id: 123456)

Cependant, lorsque je consulte leur profil, l’avatar est toujours vide. De plus, je constate qu’aucun nouvel upload n’a été effectué sur S3 récemment (aucun dans les 6 dernières heures). Je pense donc que les images optimisées ne sont pas générées en conséquence.


La bonne nouvelle, c’est que lorsque je recherche un avatar via une commande Rails :

User.find_by_username('username').uploaded_avatar

source

Les enregistrements semblent corrects et les URL pour tous les liens S3 que j’ai vérifiés jusqu’à présent fonctionnent. Les enregistrements semblent cohérents avec une autre instance qui utilise S3 depuis le début.

Ensuite, lorsque j’utilise :
OptimizedImage.where(upload_id: upload_id).where(version: 2)

Sur l’ancienne instance, je vois plusieurs images optimisées. Mais sur la nouvelle instance, il n’y a aucun enregistrement. Ce qui semble correct. Pour cet utilisateur avec custom_upload_id défini, il semble y avoir des images optimisées sur S3, mais ces enregistrements datent de plusieurs jours.

Il semble donc que je doive simplement trouver un moyen de déclencher la génération des images d’avatar optimisées.

La nouvelle instance est actuellement en mode lecture seule, je ne sais pas si cela pourrait être un facteur. Le recalcul des posts semblait fonctionner correctement en mode lecture seule.


Édition : Je vois beaucoup de tâches dans Sidekiq pour la création de miniatures d’avatar :slight_smile:

Il faut peut-être simplement sortir du mode lecture seule pour permettre leur traitement. Je tiendrai au courant.

Donc, je vois que Jobs::CreateAvatarThumbnails s’exécute dans Sidekiq. Mais rien n’a été téléchargé dans le bucket S3 depuis 9 heures. Je ne sais donc pas trop quoi en penser.