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 Mi Piace

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 Mi Piace

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 Mi Piace

@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 Mi Piace

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

4 Mi Piace

Team, I got stucked in the situation related with the Profile Picture and it wasted around 6 hours of me :frowning: but I found the perfect solution, so sharing here.

STORAGE: Using AWS S3 with CDN in front.

Problem.1: I was able to upload the profile pic from the change profile pic area but it was not reflecting in the profile. I updated my code to the latest Discourse and it started reflecting the profile picture on the UI :slight_smile:

OLD CODE - Was not showing the profile pic


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:LATEST CODE - Started showing the profile pic for new uploads

module FileStore

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

Note: Please guys keep updating your own code with the Discourse upstream on regular basis and it will keep our code updated with security fixes and also, bug free.

Problem.2: Me and my team tried changing profile pictures before fixing the above bug mentioned in the Problem.1. And, it created lots of entries in the uploads table with unknown as the value in the extension column. The code was not correctly processing the profile picture in the image optimization process (MODEL: OptimizedImage) due to wrong s3 file path.

So, I also found a workaround to fix these type of entries those happenend before my code fix.

Solution

Multi Site
We can run the below code directly on the production rails console - or using a rake task.

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
We can run the below code directly on the production rails console - or using a rake task.

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 }

I think, it will help lots of people :slight_smile:

Thank You

2 Mi Piace

@supermathie Grazie per il tuo consiglio. Se sembra che tutte le immagini ottimizzate per gli avatar siano mancanti, sarebbe sufficiente eseguire semplicemente la seconda riga?

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

Ho giĂ  eseguito un post rebake, che ha richiesto molto tempo. Quindi, idealmente, vorrei evitare di cancellare i file ottimizzati esistenti per le immagini dei post, se possibile.

2 Mi Piace

probabilmente, ma è molto possibile che il codice sia cambiato; non lo controllo da un po’ di tempo.

Farò delle ricerche…

1 Mi Piace

Grazie @supermathie, lo apprezzo molto! :slight_smile:

Quindi ho provato (solo la seconda riga), ma non sembra funzionare. Ha restituito molti record come:

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

Ne ho trovato uno con custom_upload_id impostato su un ID e ho recuperato il profilo dell’utente usando: User.find_by(id: 123456)

Tuttavia, quando visualizzo il loro profilo, l’avatar risulta ancora vuoto. Inoltre, posso vedere che non sono stati effettuati nuovi caricamenti su S3 di recente (nessuno nelle ultime 6 ore). Quindi non credo che le immagini ottimizzate vengano generate come conseguenza.


La buona notizia è che quando cerco un avatar tramite un comando Rails:

User.find_by_username('username').uploaded_avatar

source

I record sembrano corretti e gli URL per tutti gli URL S3 che ho controllato finora funzionano. I record sono coerenti con un’altra istanza che ha utilizzato S3 fin dall’inizio.

Poi, quando uso:
OptimizedImage.where(upload_id: upload_id).where(version: 2)

Nell’istanza precedente, vedo un sacco di immagini ottimizzate. Ma nella nuova istanza, non ci sono record. Il che sembra corretto. Per quell’utente con l’ID di caricamento personalizzato impostato, sembrano esserci immagini ottimizzate per lui su S3, ma quei record risalgono a giorni fa.

Quindi sembra che debba solo trovare un modo per attivare la generazione delle immagini avatar ottimizzate.

La nuova istanza è attualmente in modalità sola lettura; non sono sicuro se questo possa essere un fattore. La ricottura dei post sembrava funzionare bene in modalità sola lettura.


Modifica: vedo molti job in Sidekiq per la creazione di miniature degli avatar :slight_smile:

Quindi forse devo solo uscire dalla modalitĂ  sola lettura per permettere loro di essere elaborati. Aggiorno.

Quindi vedo che Jobs::CreateAvatarThumbnails viene eseguito in Sidekiq. Ma nulla è stato caricato nel bucket S3 da 9 ore. Quindi non sono sicuro di cosa pensare.