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 个赞

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 个赞

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 个赞

@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 个赞

作为上述命令的后续,执行 rake posts:rebake 将重新生成所有(?)其他缺失的优化图片。

4 个赞

各位团队成员,我在头像相关的问题上卡住了,白白浪费了我大约 6 个小时 :frowning: 但我找到了完美的解决方案,所以在此分享。

存储:使用 AWS S3,前面配有 CDN

问题 1:我能够从“更改头像”区域上传头像,但上传后在个人资料页面没有显示。我将代码更新到最新的 Discourse 版本后,头像开始在界面上正确显示 :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 上游同步更新,这样可以确保我们的代码包含安全修复,并且避免 bug。

问题 2:我和团队在修复上述 问题 1 中提到的 bug 之前,尝试过更改头像。这导致在 uploads 表中产生了大量条目,其中 extension 列的值为 unknown。由于 S3 文件路径错误,代码在图片优化流程(模型: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:

谢谢

2 个赞

@supermathie 感谢您的建议。如果所有头像的优化图片似乎都缺失了,仅运行第二行代码是否可能就足够了?

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

我已经执行了帖子重新烘焙,这花费了相当长的时间。因此,如果可能的话,我希望能避免删除现有的帖子图片优化文件。

2 个赞

可能,但代码很可能已经更改;我有一段时间没看过那块了。

我去问问……

1 个赞

感谢 @supermathie,我很感激!:slight_smile:

所以我尝试了一下(只试了第二行),但似乎不起作用。返回了很多类似以下的记录:

id: 1234,
user_id: 1234,
custom_upload_id: nil,
gravatar_upload_id: nil,
last_gravatar_download_attempt: 2015 年 5 月 7 日 星期四 09:40:35 UTC +00:00,
created_at: 2015 年 5 月 7 日 星期四 09:40:35 UTC +00:00,
updated_at: 2015 年 5 月 7 日 星期四 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)

在之前的实例中,我看到许多优化后的图片。但在新实例中,没有任何记录。这似乎是正确的。对于那个设置了自定义上传 ID 的用户,S3 上似乎确实存在他们的优化图片,但这些记录是几天前的。

因此,看来我只需要找到一种方法来触发生成优化后的头像图片。

新实例目前处于只读模式,不确定这是否是一个影响因素。在只读模式下重新烘焙帖子似乎正常工作。


编辑:我在 Sidekiq 中看到很多用于创建头像缩略图的作业 :slight_smile:

所以也许只需要退出只读模式,让它们得以处理。我会继续更新。

我看到 Sidekiq 中正在运行 Jobs::CreateAvatarThumbnails。但过去 9 小时内没有任何文件上传到 S3 存储桶,所以不太清楚这意味着什么。