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?

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…

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

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

위 명령의 후속 작업으로, rake posts:rebake를 실행하면 다른 누락된 최적화 이미지(?)를 모두 다시 생성합니다.

팀원 여러분, 프로필 사진 관련 문제로 인해 약 6시간을 낭비했습니다. :frowning: 하지만 완벽한 해결책을 찾았으니 여기 공유합니다.

스토리지: AWS S3를 사용하고 앞에 CDN을 구성했습니다.

문제.1: 프로필 사진 변경 영역에서 프로필 사진을 업로드할 수는 있었지만, 프로필에 반영되지 않았습니다. 제 코드를 최신 Discourse 버전으로 업데이트하니 UI에 프로필 사진이 반영되기 시작했습니다 :slight_smile:

구버전 코드 - 프로필 사진이 표시되지 않음


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

해결책: 최신 코드 - 새로운 업로드에 대해 프로필 사진 표시 시작

module FileStore

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

참고: 여러분도 Discourse upstream을 정기적으로 업데이트하여 코드를 최신 상태로 유지해 주세요. 이를 통해 보안 패치와 버그 수정이 적용됩니다.

문제.2: 위 문제.1에서 언급된 버그를 수정하기 전에 저와 팀원들은 프로필 사진을 변경했습니다. 그 결과 uploads 테이블에 extension 컬럼의 값이 unknown인 항목이 많이 생성되었습니다. 잘못된 s3 파일 경로로 인해 이미지 최적화 과정 (MODEL: OptimizedImage) 에서 프로필 사진이 올바르게 처리되지 않았습니다.

따라서, 제 코드 수정 전에 발생했던 이러한 유형의 항목을 수정하기 위한 임시 해결책도 찾았습니다.

해결책

멀티 사이트
아래 코드를 프로덕션 rails 콘솔에서 직접 실행하거나 - 또는 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

일반 - 단일 사이트
아래 코드를 프로덕션 rails 콘솔에서 직접 실행하거나 - 또는 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 }

많은 분들에게 도움이 될 것 같습니다 :slight_smile:

감사합니다

@supermathie 조언해 주셔서 감사합니다. 아바타용 최적화 이미지가 전부 없는 것처럼 보인다면, 두 번째 줄만 실행하면 충분한가요?

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

이미 포스트 리베이킹을 한 번 수행했는데, 꽤 오랜 시간이 걸렸습니다. 가능하면 기존 포스트 이미지의 최적화 파일을 지우는 것은 피하고 싶습니다.

아마도 그렇겠지만, 코드가 변경되었을 가능성도 매우 큽니다. 꽤 오랫동안 그 부분을 확인하지 않았거든요.

주변에 물어봐 볼게요…

고맙습니다 @supermathie, 정말 감사해요! :slight_smile:

그래서 일단 시도해 봤어요 (두 번째 줄만). 하지만 작동하지 않는 것 같습니다. 다음과 같은 레코드가 많이 반환되었거든요:

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

custom_upload_id가 특정 id로 설정된 레코드를 하나 찾아서 User.find_by(id: 123456)를 사용해 해당 사용자의 프로필을 확인했습니다.

하지만 프로필을 열면 아바타가 여전히 비어 있습니다. 또한 최근 6시간 동안 S3에 새로운 업로드가 없었습니다. 따라서 최적화된 이미지가 생성되지 않은 것으로 보입니다.


좋은 소식은, rails 명령어로 아바타를 검색할 때:

User.find_by_username('username').uploaded_avatar

source

레코드들이 올바르게 보이고, 지금까지 확인한 모든 S3 URL이 정상적으로 작동한다는 점입니다. 레코드들은 S3를 처음부터 사용해 온 다른 인스턴스와 일치하는 것으로 보입니다.

그런 다음 다음을 사용할 때:
OptimizedImage.where(upload_id: upload_id).where(version: 2)

이전 인스턴스에서는 최적화된 이미지가 여러 개 보였습니다. 하지만 새로운 인스턴스에서는 레코드가 없습니다. 이는 정상적인 것으로 보입니다. custom_upload_id가 설정된 그 사용자의 경우, S3에는 최적화된 이미지가 있지만, 해당 레코드들은 며칠 전 것들입니다.

즉, 최적화된 아바타 이미지 생성을 트리거하는 방법을 찾아야 할 것 같습니다.

현재 새로운 인스턴스는 읽기 전용(Read Only) 모드에 있으며, 이것이 영향을 미치는지 확실하지 않습니다. 읽기 전용 모드에서 게시물 재구축(Rebaking)은 잘 작동했습니다.


수정: sidekiq에서 아바타 섬네일 생성을 위한 작업(jobs)이 많이 보입니다. :slight_smile:

아마도 읽기 전용 모드를 종료해야 처리가 가능할 것 같습니다. 업데이트하겠습니다.

Sidekiq에서 Jobs::CreateAvatarThumbnails가 실행되고 있는 것을 확인했습니다. 하지만 9시간 동안 S3 버킷에 아무것도 업로드되지 않았습니다. 그래서 이게 무슨 의미인지 잘 모르겠습니다.