如何恢复缺失的头像?

我们遇到了一个与此类似的 bug

https://meta.discourse.org/t/missing-user-profile-pictures/93844

有什么方法可以恢复缺失的头像吗?

附:我尝试了 这篇指南 并运行了 rake avatars:refresh,但没有任何效果。

这个问题像病毒一样,正在蔓延到更多头像!有一个奇怪的观察结果:

在 Firefox 中显示了一些头像,但在 Chrome 中却缺失了。但这并不意味着 Firefox 中没有缺失的头像——Firefox 中也有缺失的头像!

Firefox 截图

Chrome 截图

这个 bug 真的已经被 修复 了吗?

我也遇到了同样的问题,目前正在调查中。在我调查的案例中,这与外部存储有关。

@Pad_Pors 您是否仍然遇到此问题?另外,您是否曾经或将数据上传存储在 S3 中?

很高兴听到有专家正在调查此事 :ok_hand:

是的,我们仍然面临这个问题,而且是的,我们过去将上传内容存储在 S3 上,但现在不再如此。

我们这边也一样,@angus,我们确实有 S3。如果您需要日志或其他信息,请随时告知。非常感谢。

在我所查看的案例中,缺失的头像图片在命令行升级以及手动将 PostgreSQL 从 10 升级到 12 之后,被移到了 S3 中的 tombstone 文件夹。我目前仍不确定具体原因。

查找上传文件

@Jeremie_Leroy @Pad_Pors 如果您想确认您的情况是否相同,以下是我在 S3 的 tombstone 文件夹中检查缺失头像的方法:

  1. 获取一个已知在迁移后损坏的头像上传的 SHA1(即上传 URL 中的 16 位字符串)。具体做法是:从损坏头像的上传 URL 中提取上传 ID(它是文件名的第一部分,例如对于 6254_2.png,ID 为 6254),然后使用该 ID 在最近的数据库转储中查找该上传的 SHA1。如果您不习惯使用命令行,可以使用 PostgreSQL 图形界面工具(如 https://eggerapps.at/postico/)来可视化转储中的数据。

  2. 使用 AWS CLI 在相关 S3 存储桶的 tombstone 文件夹中搜索该 SHA1。

    aws s3api list-objects --bucket <bucket_name> --query "Contents[?contains(Key, <sha1>)]" --prefix "tombstone"
    

    (您需要将 <bucket_name><sha1> 替换为实际值)

如果成功,您将得到如下所示的结果列表:

{
  "Key": "tombstone/original/2X/d/d7b553ff276fca054c7090e859ef5339fd1f936e.jpg",
  "LastModified": "2020-05-16T11:45:03+00:00",
  "ETag": ## 字母和数字组成的字符串,
  "Size": 64580,
  "StorageClass": "STANDARD",
  "Owner": {
     "ID": ## 字母和数字组成的字符串
   }
}

请注意,5 月 16 日是我执行升级的日期。所有被错误 tombstone 的头像的时间戳都大致在那个时间附近。我怀疑该问题由于缓存原因,在生产环境中延迟了一段时间才显现,并且是间歇性出现的。

恢复

据我所知,UploadRecovery(及其关联的 rake 任务)仅针对帖子上传,无法处理已被 tombstone 的头像。

我目前正在尝试为 UploadRecovery 添加(补丁)一个新方法,该方法使用 recover_from_s3 来恢复头像上传。

如果您知道其他更简单的方法来恢复 S3 中被错误 tombstone 的头像,欢迎随时告知。

@tgxworld 有什么建议吗?

这对我来说有点棘手,我们这种情况的人多吗?如果有的话,那值得为此开发一个更新吗?@sam @codinghorror

感谢 @angus 分享排查路径,但我们已不再使用 AWS 和 S3。事实上,如果我没记错的话,问题是在我们从 AWS 迁移后才开始的。

如果问题能被修复,我当然很高兴。但目前对我来说,让那几位用户重新上传头像要容易得多,并希望这个问题不会蔓延到新用户身上!

我已在管理的网站上成功解决了此问题,方法是采用了一种经过调整的逻辑,用于恢复帖子中被错误标记为已删除的图片:discourse/lib/upload_recovery.rb at main · discourse/discourse · GitHub

@Jeremie_Leroy 我之所以在上面列出这些步骤,部分原因是头像缺失可能由多种原因导致。要确定此方法是否适用于您,首先需要确认是否存在被错误标记为已删除的头像,即您遇到的具体问题原因。

我也理解,如果您不熟悉 Discourse 的技术细节,进行此类分析会非常困难。我已将我所使用的解决方案封装为一个插件,您可以在自己的网站上尝试。请参见下方的说明。

@Pad_Pors 如果您只是希望让用户重新上传头像,我建议直接这样做,而不要尝试此修复方案。


说明

请注意,此修复方案仅适用于以下情况下的头像缺失问题:

  • 上传文件存储在 S3 上
  • 头像缺失是因为它们被错误地标记为已删除(tombstoned)
  • 该头像的上传记录仍然存在

请在论坛活跃度较低的时段执行此操作,并首先进行完整备份。

安装此插件

该插件为 UploadRecovery 添加了 recover_avatars 方法,并采用了一种经过调整的恢复方法,该方法与主 recover 方法(用于恢复帖子中缺失的上传文件)所使用的逻辑相同。

此方法会将“已恢复”的头像副本保留在 tombstone 文件夹中以备冗余。这些副本将由 purge_deleted_uploads 后台作业删除,该作业根据站点设置 purge_deleted_uploads_grace_period_days 设定的周期运行。

进入 Rails 控制台

要使用此方法,您需要先通过 SSH 登录到您的服务器,进入 Docker 实例并启动 Rails 控制台:

./launcher enter app
rails c

进行测试运行

要查看该方法将尝试从 tombstone 中恢复哪些上传文件,请先执行一次测试运行:

UploadRecovery.new(dry_run: true, stop_on_error: false).recover_avatars

这将列出用户名和 S3 文件链接。这些是实际运行时该方法将尝试从 tombstone 中移出的头像文件:

示例输出

user1 tombstone/original/2X/b/bc84397936074854226f1c6e9016099b7fc0aca7.jpeg
user2 tombstone/original/2X/b/b8588e7e45804406f2cbe86f2362c2ccf7f13155.jpg
user3 tombstone/original/2X/8/81a4e3b70cdc35e8f61bca87d276d0253152804a.jpeg

请将其与您的网站上缺失头像的用户进行对比。

执行实际运行

dry_run 参数改为 false 以执行实际运行:

UploadRecovery.new(dry_run: false, stop_on_error: false).recover_avatars

检查

任务完成后,请在新的无痕窗口中检查您的在线站点(以避免缓存问题)。完成后,请务必关闭与服务器的活动 SSH 连接。您不希望不小心在打开的 Rails 控制台中输入错误的命令。