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 Me gusta

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 me gusta

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 me gusta

@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 Me gusta

Como seguimiento al comando anterior, ejecutar rake posts:rebake regenerará todas (?) las demás imágenes optimizadas que falten.

4 Me gusta

Equipo, me quedé atascado en una situación relacionada con la Imagen de perfil y me hizo perder alrededor de 6 horas :(, pero encontré la solución perfecta, así que la comparto aquí.

ALMACENAMIENTO: Usando AWS S3 con CDN al frente.

Problema 1: Podía subir la imagen de perfil desde el área de cambio de imagen, pero no se reflejaba en el perfil. Actualicé mi código a la última versión de Discourse y comenzó a mostrar la imagen de perfil en la interfaz :slight_smile:

CÓDIGO ANTIGUO - No mostraba la imagen de perfil


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

SOLUCIÓN: CÓDIGO ACTUALIZADO - Comenzó a mostrar la imagen de perfil para las nuevas subidas

module FileStore

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

Nota: Por favor, mantengan actualizado su propio código con el flujo principal de Discourse de forma regular; esto mantendrá nuestro código actualizado con correcciones de seguridad y también libre de errores.

Problema 2: Mi equipo y yo intentamos cambiar las imágenes de perfil antes de corregir el error mencionado en el Problema 1. Esto creó muchas entradas en la tabla uploads con el valor unknown en la columna extension. El código no procesaba correctamente la imagen de perfil en el proceso de optimización de imágenes (MODELO: OptimizedImage) debido a la ruta incorrecta del archivo en S3.

Así que también encontré una solución alternativa para corregir este tipo de entradas que ocurrieron antes de mi corrección de código.

Solución

Multi sitio
Podemos ejecutar el siguiente código directamente en la consola de Rails de producción o mediante una tarea 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 - Sitio único
Podemos ejecutar el siguiente código directamente en la consola de Rails de producción o mediante una tarea 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 }

Creo que esto ayudará a muchas personas :slight_smile:

Gracias

2 Me gusta

@supermathie Gracias por tu consejo. Si parece que faltan todas las imágenes optimizadas para avatares, ¿sería suficiente simplemente ejecutar la segunda línea?

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

Ya realicé una nueva cocción de las publicaciones, lo cual tomó bastante tiempo. Por lo tanto, idealmente evitaría borrar los archivos optimizados existentes para las imágenes de las publicaciones si es posible.

2 Me gusta

Probablemente, pero es muy posible que el código haya cambiado; no lo he revisado desde hace un tiempo.

Preguntaré alrededor…

1 me gusta

Gracias @supermathie, ¡lo aprecio! :slight_smile:

Así que procedí a probarlo (solo la segunda línea), pero parece que no funciona. Devolvió muchos registros como:

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

Encontré uno con custom_upload_id establecido a un ID y localicé el perfil del usuario usando: User.find_by(id: 123456)

Sin embargo, al ver su perfil, la imagen de perfil sigue vacía. Además, puedo ver que no se han realizado nuevas subidas a S3 recientemente (ninguna en las últimas 6 horas). Así que creo que las imágenes optimizadas no se están generando como resultado.


La buena noticia es que, cuando busco una imagen de perfil mediante un comando de Rails:

User.find_by_username('username').uploaded_avatar

source

Los registros parecen correctos y las URLs de todas las URLs de S3 que he verificado hasta ahora funcionan. Los registros son consistentes con otra instancia que ha utilizado S3 desde el principio.

Luego, cuando uso:
OptimizedImage.where(upload_id: upload_id).where(version: 2)

En la instancia anterior, veo varias imágenes optimizadas. Pero en la nueva instancia, no hay registros. Lo cual parece correcto. Para ese usuario con el ID de subida personalizado establecido, parece haber imágenes optimizadas para él en S3, pero esos registros son de hace días.

Parece que solo necesito encontrar una manera de activar la generación de las imágenes de perfil optimizadas.

La nueva instancia está actualmente en modo de solo lectura; no estoy seguro si eso podría ser un factor. La regeneración de publicaciones funcionó bien en modo de solo lectura.


Edición: Veo muchos trabajos en Sidekiq para crear miniaturas de imágenes de perfil :slight_smile:

Así que tal vez solo necesito salir del modo de solo lectura para permitir que se procesen. Actualizaré.

Así que veo que Jobs::CreateAvatarThumbnails se está ejecutando en Sidekiq. Pero nada se ha subido al bucket de S3 en 9 horas. Así que no sé qué pensar de eso.