@RGJ 同样,我真诚地表示,如果任何人能确切知道如何避免重建所有图片的徒劳工程,我非常支持;如果我是经验丰富的 Discourse 开发者并且知道如何轻松完成,我可能一开始就会那样做。
我猜测,对于拥有大量图片的用户来说,迁移出 S3 并不是常见情况,因此与为 Discourse 添加更具普遍实用性的功能相比,这很难值得花费时间。我从 Google+ 导入到 MakerForums 时大约有 100GB 的上传数据,我们当时选择 S3 是考虑到可能会有很多人从那些社区迁移到 MakerForums,但最终只有少数社区活跃迁移,因此持续增长并不支持继续留在 S3。我认为这是一个相当极端的特例,而重新处理图片是一次性成本。
最后,我非常感谢你首先提出这个话题,否则我很容易就会错过非帖子上传的内容。
…
@RGJ 你显然说得对,销毁并重建并不是好办法。我添加了一个检查:raise "Error: upload url #{url} changed to #{new_upload.short_url}, should be unchanged." if url != new_upload.short_url,这至少能报告源数据损坏的问题。今天 Digital Ocean Spaces 的故障 导致它向我发送了损坏的数据,触发了许多上传的错误——我不知道具体有多少。但由于旧的上传已经被销毁,我现在有一些损坏的页面,而我直到丢失了包含日志的滚动记录(其中指出了哪些页面损坏)后才意识到这一点,因此我甚至无法通过备份手动修复它们。
因此,虽然我的工作相比旧方法有所改进,因为它至少能报告一些错误,但更好的做法是下载文件,检查下载文件的 SHA1 值,然后将其写入本地文件。同时,我已修改我的 PR,使其在任何未处理的错误发生时停止迁移,以至少限制数据丢失。
我仍然认为我的工作应该被合并,因为这是一种帕累托改进:它不会让情况变得更糟,反而有所改善。但最好还是用正确的方式来做。我认为正确的方式是编写 lib/file_store/from_s3_migration.rb,使其与 lib/file_store/to_s3_migration.rb 并行,但我目前还做不到。
由于我的 PR 尚未被审查,我又往里面添加了一些内容。我添加了一个 uploads:report_missing_uploads 任务,它会遍历 raw 字段,查找 upload://... 实例,其中对应的上传对象不存在。至少在我的情况下,借助备份,我将能够检查备份,找到孤立的文件并将其恢复到站点,然后重新生成这些帖子以恢复丢失的图片。我已经找到了 678 个需要搜索的实例,其中目前只找到了 10 个未找到的,因此我很高兴写了这个测试!在我进入重新生成剩余帖子的阶段之前,需要先处理这个问题。
…
我已完成迁移的第一阶段,不包括对共享上传的受影响帖子进行重新生成,也不包括非帖子上传。在完成另一次远程备份后,我计划测试这些功能并将其添加到我的 PR 中。
…
我现在已开始测试迁移的下一阶段:重新生成和非帖子上传迁移。我的第一个教训是,由于引用帖子中的非帖子上传头像,将重新生成作为下一步会失败,因此重新生成帖子必须是最后一步。
下一个发现:感谢外键约束!在迁移非帖子上传时,我发现至少需要先迁移个人资料,然后再进行一般的非帖子上传迁移。
ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR: update or delete on table "uploads" violates foreign key constraint "fk_rails_1d362f2e97" on table "user_profiles"
个人资料迁移很棘手,因为我必须迁移附加到个人资料的两个上传,但在某些情况下人们为两者使用了相同的图片,因此我必须分三个阶段完成这项工作。我已成功迁移了我站点上所有带有 S3 URL 的个人资料。
我已迁移了所有非帖子、非个人资料的上传。@RGJ,如果你想试用我发布的分支,它已包含我的最新工作。其中的所有内容都已用于一次完整的站点迁移。
…
@cvx 我不知道你何时能有机会审查,但如果没有我的 PR,migrate_from_s3 肯定充满了静默数据破坏的漏洞。我所做的并不完美,但它确实防止了我实际遇到的许多漏洞。
我已经完成了目前打算在这里做的所有工作。我已经迁移了我的站点,这意味着我甚至无法有效评估任何请求的更改。如果你拒绝这个 PR,我强烈建议你直接删除现有的迁移,因为它会静默地破坏用户的数据。
关于 PR,我有时会在 CI 中出现测试失败(如当前版本),类似于以下内容:
7867 examples, 0 failures, 11 pending, 1 error occurred outside of examples
##[error]Process completed with exit code 1.
这在我本地无法复现(到目前为止),而且我在 CI 日志中看不到任何信息说明 CI 中出了什么问题,因此我不会再浪费时间尝试在 CI 输出中寻找隐藏信息。
最后一点:在完成迁移后,我们发现一些用户的个人资料图片在迁移过程中丢失,他们正在手动恢复。我猜测可能需要额外的代码才能成功完成该操作,但由于我在为时已晚时才意识到这一点,我没有测试用例来验证这一点。因此,这是一个可能在一些配置中引发问题的剩余漏洞,但我已无法再编写额外的修复。