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 curtidas

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 curtida

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 curtida

@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 curtidas

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

4 curtidas

Equipe, fiquei preso em uma situação relacionada à Foto de Perfil e isso desperdiçou cerca de 6 horas da minha vida :(, mas encontrei a solução perfeita, então estou compartilhando aqui.

ARMAZENAMENTO: Usando AWS S3 com CDN na frente.

Problema 1: Consegui fazer o upload da foto de perfil na área de alteração de foto, mas ela não aparecia no perfil. Atualizei meu código para a versão mais recente do Discourse e a foto de perfil começou a aparecer na interface :slight_smile:

CÓDIGO ANTIGO - Não mostrava a foto 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

SOLUÇÃO: CÓDIGO MAIS RECENTE - Começou a mostrar a foto de perfil para novos 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

Nota: Pessoal, por favor, mantenham seu código atualizado com o Discourse upstream regularmente. Isso manterá nosso código atualizado com correções de segurança e também livre de bugs.

Problema 2: Eu e minha equipe tentamos alterar as fotos de perfil antes de corrigir o bug mencionado no Problema 1. Isso criou muitas entradas na tabela uploads com o valor unknown na coluna extension. O código não estava processando corretamente a foto de perfil no processo de otimização de imagens (MODELO: OptimizedImage) devido ao caminho incorreto do arquivo no S3.

Então, também encontrei uma solução alternativa para corrigir esse tipo de entrada que ocorreu antes da minha correção no código.

Solução

Multi Site
Podemos executar o código abaixo diretamente no console rails de produção - ou usando uma tarefa 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 - Single Site
Podemos executar o código abaixo diretamente no console rails de produção - ou usando uma tarefa 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 }

Acho que isso ajudará muitas pessoas :slight_smile:

Obrigado

2 curtidas

@supermathie Obrigado pelo seu conselho. Se parecer que todas as imagens otimizadas para avatares estão faltando, apenas executar a segunda linha provavelmente seria suficiente?

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

Eu já fiz um rebake de post, o que levou bastante tempo. Então, idealmente, gostaria de evitar apagar os arquivos otimizados existentes para imagens de post, se possível.

2 curtidas

provavelmente, mas é muito possível que o código tenha mudado; não olho para isso há algum tempo.

Vou perguntar…

1 curtida

Obrigado @supermathie, agradeço muito! :slight_smile:

Então, tentei aplicar a segunda linha, mas parece que não está funcionando. Retornou muitos 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>,

Encontrei um com custom_upload_id definido para um ID e localizei o perfil do usuário usando: User.find_by(id: 123456)

Ao visualizar o perfil dele, no entanto, o avatar ainda está vazio. Além disso, percebi que não houve novos uploads para o S3 recentemente (nenhum nas últimas 6 horas). Então, acho que imagens otimizadas não estão sendo geradas como resultado.


A boa notícia é que, ao buscar um avatar via comando do Rails:

User.find_by_username('username').uploaded_avatar

source

Os registros parecem corretos e os URLs de todos os links do S3 que verifiquei até agora funcionam. Os registros são consistentes com outra instância que sempre usou o S3 desde o início.

Depois, ao usar:
OptimizedImage.where(upload_id: upload_id).where(version: 2)

Na instância anterior, vejo várias imagens otimizadas. Mas na nova instância, não há registros. O que parece correto. Para aquele usuário com custom_upload_id definido, parecem existir imagens otimizadas para ele no S3, mas esses registros são de dias atrás.

Então, parece que preciso apenas encontrar uma maneira de disparar a geração das imagens de avatar otimizadas.

A nova instância está atualmente em modo somente leitura. Não sei se isso pode ser um fator. Reassentar posts parece ter funcionado bem no modo somente leitura.


Edição: Vejo muitos jobs no Sidekiq para criar miniaturas de avatar :slight_smile:

Então, talvez eu só precise sair do modo somente leitura para permitir que eles sejam processados. Vou atualizar.

Então, vejo que Jobs::CreateAvatarThumbnails está sendo executado no Sidekiq. Mas nada foi enviado para o bucket S3 nas últimas 9 horas. Então, não sei o que pensar disso.