Migrate_from_s3 の問題

When migrating from S3 to local storage, we see a number of issues.

The main issue is that the migrate_from_s3 rake task is not taking the Uploads table as a starting point, but the posts. This causes it to skip a lot of uploads which are being left on S3.

  • uploads used as logo’s because they are not referenced in a post
  • uploads for avatars because they are not referenced in a post
  • uploads that are (for some reason) referenced by their CDN URL in raw because they do not match the regex that is being used to identify the uploads
  • uploads that are on non-AWS S3 storage because they do not match the regex because it requires amazonaws in the URL
  • uploads that for some reason do not match the second, different regex (we’re seeing this with non-image uploads like mp3 files, not sure why this is happening)
「いいね!」 2

We’re working on improving the way we associate uploads to posts (by using the upload:// scheme) that will make these storage migrations much more bulletproof. There’s little point to fixing these rake tasks before that’s done.

「いいね!」 7

最近、一度に少ない数の投稿を移行できるようにする新しい PR を作成し、そのタスクに関するテストも追加しました。

まずは投稿から始めるのが妥当だと感じています。各移行後に URL を変更するために、加工された投稿を再レンダリング(rebake)する必要があるからです。すべてのアップロードを先に移行してから再レンダリングを開始すると、大規模なサイトの場合、サイトが長時間にわたって破損した状態になる可能性があります(私は S3 からローカルへ約 100GB を移行する必要があるので、この点は重要です)。ただし、私が記述した内容は、migrate_from_s3 の後に実行され、投稿に含まれていないアップロードを整理するための migrate_uploads_from_s3 タスクの作成を始めるのに役立つかもしれません。

@zogstrip 「We’re working on…」の現在の状況はどうなっていますか?まだ流動的な状態ですか、それともこの移行に注目する価値がある状態ですか?

「いいね!」 5

投稿とアップロードの関連性をより明確にするため、アップロード機能に関して多くの改善を行ってきました。

これらの移行タスクは、必要に応じてさらに改善可能です :+1:

「いいね!」 2

オフタイムにバッチアップロードを使ってサイトを移行できるようになったら、投稿以外のアップロードを検討する価値があるかどうかを確認します!:smiling_face: PR のレビュー、ありがとうございます!

「いいね!」 1

次に扱うべきことが 2 つあります。まず 1 つ目は、制限は有用ですが、あくまで検索空間に対する制限である点です。次に、変更する投稿の最大数を指定できるようにしたいと考えています。そのため、クエリの制限に加え、変更する投稿の最大数も追加したいと考えています。

また、max を指定する際は、デバッグ目的で処理対象を明確に示すことが理にかなっています。したがって、maxnil でない場合は出力を詳細(verbose)にしたいと考えています。これにより、この作業の主なユースケースである「続行する前にプロセスを検証する」ことが可能になります。

私の考えでは、最初の引数に max を、2 番目の引数にオプションの limit を指定するようにします。なぜなら、max が最も重要であり、limit は「1 回のリクエストのみ」のコストを下げるためのものだからです。

2 つ目は、非アップロード(non-upload)関連のアップロードです。1 年以上前、Google+ から Discourse への移行方法を模索している最中に、参加していた Discourse サイトに動画をアップロードしようとしました。その際、生成された URL は https://#{SiteSettings.absolute_base_url}/original/3X/b/a/ba9e06ebc2f4397f26793bb5cd4e169308dd371d.mp4 となっていました。

現在、動画をアップロードすると、![file_example_MP4_480_1_5MG|video](upload://caJ9ykkpshw3PFK4464VUIPWJ4l.mp4) のような形式になります。

直近のテストでは、migrate_from_s3 がこれらの URL を完全に破損させ、もはや URL として機能しない状態にしてしまいました。これは確実に修正する必要があります。その後、このタスクが実際には ![text](non-upload-url-to-migrate) 形式の URL に遭遇することは少ないと予想されるため、まずは正規表現で両方のケースを処理して可読性を低下させるのではなく、マジックな upload プロトコルの周りに Markdown リンクを追加するアプローチを取りたいと考えています。ただし、この方針を変更する可能性もあります。

video または audio タグは、JavaScript 内の正規表現マッチによって追加されているようです。そのため、それらを正しく識別するために、app/assets/javascripts/discourse/app/lib/uploads.js 内の正規表現をタスクにコピーする必要があります。次回このコードに触れる人が更新元がわかるように、正規表現のソースも記載します。:stuck_out_tongue:

今夜、この作業に取り組む時間を確保し、ドラフトの PR を作成しました。まだ完成していません。バグが残っていることは承知しています。現時点では、upload: 疑似プロトコル URL(画像の標準的なもの)の動作は変更していないつもりですが、健全性チェック(sanity check)を追加しました。

この PR の変更により、通常の upload: 疑似プロトコルによるアップロードと、S3(私の場合は DigitalOcean Spaces)への参照で明示的に参照されている動画を、どちらも正常に移行できました。このコマンドを使用して、1 つの投稿ずつ変更しています。

bin/rake uploads:batch_migrate_from_s3[1,1000]

なお、これはデータベースクエリからある程度ランダムに取得された最初の 1000 件の投稿を超えて実行されません。この低い制限は、1 つの投稿ずつ移行しながらクエリを高速に実行し、その投稿の動作を確認してから、次のものを見つけるために再度開始するためのものです。このコマンドがこのように動作するのは、現在私が作業中の PR がある場合に限られます!

作業を進めるにつれて診断出力を追加しており、これが開発以上の重要性を持っていると考えるようになっています。DigitalOcean Spaces からの一時的なダウンロード失敗が多数発生しており、投稿内の一部のファイルのみが移行され、残りが移行されないという状況が見られます。元のコードでは、これは . を表示して処理を続行し、最後に Done と表示するだけですが、実際にはタスクは完了していません。ある投稿を完全に移行するまでに、5〜6 回の実行が必要でした。(最初はローカルバグのデバッグだと思っていたため、回数を数えていませんでした。)診断出力がクリーンになるまで、この移行を同じ制限値で繰り返し実行する必要があると考えています。そのため、max が設定されている場合のみ詳細な進行状況を表示し、どちらの場合でも有用な警告メッセージを表示するようにしています。

現在、Discourse Spaces での断続的なダウンロード失敗に対処するために、以下のハックを使用しています。これにより、実用上の成功率が劇的に向上しています(これまでに数百件の投稿を移行しましたが、3 回のリトライで完全に十分でした)。

https://github.com/johnsonm/discourse/commit/7dfac12a2ea6ec04ba4e0616b4e0dbd1d806cff7

また、Google+ からインポートした際に、設定した制限を超えるサイズの動画が何らかの理由で存在していることを発見しました。いくつかの超大容量動画のワンショット移行を行う間、SiteSettings.max_image_size_kbSiteSettings.max_attachment_size_kb の両方を一時的に増やす必要がありました。これらの動画がどのようにしてサイト上に存在することになったのかは不明ですが、今はそれらを壊したくありません。超大容量アップロードを許可したバグが、私のインポートスクリプトにあったのか、Discourse 側にあったのか、あるいは単に私が時間経過とともに設定を変更した記憶が間違っていたのかはわかりません。:wink:

移行対象の多くが G+ からのインポートだったため、現在のバリデーションに失敗する投稿がいくつかありました。Unhandled failure: Validation failed: Sorry, new users can only put one image in a post というエラーがいくつか発生しましたが、当初はなぜそれが再発しないのか理解できませんでした。実は、アップロードは正常にローカルへ移動され、すべて upload: 疑似プロトコルを使用していたため、生データ(raw)は変更されませんでした。しかし、post.save! はバリデーションエラーで失敗し、post.rebake! が発火しない状態でした。そのため、3 万件の投稿のうちいくつかの投稿に、再焼き直し(rebake)が必要な画像が残っています。残念ながら、どの投稿が該当するかは記録していません。現在、別の修正として post.save!(validate: false) に切り替えたため、この特定の問題は再発しないはずです。未処理エラーで移行を中断するようにしたことは非常に幸いでした。そうでなければ、いくつかの投稿以上の被害が出ていた可能性があります。

移行実行中にサイトを利用可能(通知の配信を含む)に保つため、sidekiq キューへのスパムを避けたいと考えています。名前付けは、キャッシュの無効化やオフ・バイ・ワン・エラーと並んで、コンピュータサイエンスにおける最も難しい問題の 2 つのうちの 1 つだとされていますが、移行中の rebake 後に次のアイテムに移行する際に、キューに詰められることができる合計キュースロット数(ジョブスロット数ではありません)を制御するための環境変数 DISCOURSE_MIGRATION_MAX_ENQUEUED を提案します。これにより、キューへのスパムを避け、サイトが機能し続けるようにします。lib/tasks/uploads.rake 内のすべての投稿ごとの rebake に対して、デフォルト値を 0 とするパッチを作成しました。これは、本番環境での移行に使用しています。

https://github.com/discourse/discourse/blob/59a761851b9c8786d3a9692f8c595372b0534f77/lib/tasks/uploads.rake

「いいね!」 4

@zogstrip 最近、この分野での私の前の PR のレビューから文脈をお持ちですので、この PR のレビューをお願いしてもよろしいでしょうか? FIX: Make migrations from S3 more robust; fix bare URL migration by johnsonm · Pull Request #10093 · discourse/discourse · GitHub

この PR には、比較的largeなマイグレーションを実行中に修正してきた内容を含めています。すべての修正に対してテストを追加しようとはしていません。すべてのエラー形式をどのように注入すればよいか確信が持てないためです。しかし、少なくとも新しい機能についてはテストされています。

@RGJ 現在の私の PR は、CDN に関する部分を除き、あなたの最初の 2 点以外のすべての点を解決できると思います。私のサイトは CDN を使用しており、CDN URL を持つ動画をマイグレーションしましたが、これは discourse spaces の命名に関する副作用だった可能性があります。追加のケースがある場合、私の PR が正規表現への追加や、追加のバリエーションに対するテストケースの追加のための簡単な足場を提供してくれることを願っています。

投稿ごとに最初にマイグレーションを行うのが正しいと思います。投稿内のアップロードをマイグレーションした後、その投稿を再レンダリング(rebake)して、調理済みの投稿に正しい URL が含まれるようにする必要があるためです。投稿のマイグレーションが完了したら(キューの長さを直接確認するようにレート制限を変更したことで、2 週間未満で完了するかもしれません)、残りの作業を片付けていきます。

複数の投稿が同じコンテンツへの参照を共有する可能性があるため(複数の人が同じファイルをアップロードした場合など)、2 回目のパスで調理済みデータ内の古い URL をチェックし、新しい場所を取得するためにそれらの投稿を再レンダリングする必要があります。キューを過負荷にしないために、同じレート制限を使用できます。

makerforums では、新しいコンテンツを「s3」(私たちの場合は DigitalOcean Spaces)に配置するのをやめた後にブランディングを調整したため、壊れたロゴを見ることはないでしょう。しかし、少なくともアバターについては、S3 にまだアップロードが残っている可能性が高いです。投稿に関連しないアップロードのマイグレーションは、すべての投稿のマイグレーションが完了した後に開始する必要があります。私は、投稿内のアップロードのマイグレーションが完了した後、それについて文書化する必要があるでしょう。

@pfaffman エラーが再現しなかった Bizarre Problems with migrate_from_s3 - #5 を確認しました。現在の PR での私の修正がない場合、検証の失敗を含むエラーが静かに飲み込まれてしまいます。ここでの作業は、当時あなたが目にした問題の少なくともいくつかに対処できると思います。

@hosna https://meta.discourse.org/t/what-does-rake-uploads-migrate-from-s3-exactly-do/97285 で提起された問題は、この PR において部分的または完全に解決されています。完全に解決されていない場合、さらなる修正を検証するための追加のテストを追加しやすくするテストを追加しています。

@sam PR に 2.6 ラベルを付けたことから、少なくとも数日はマージされないだろうと推測します。レート制限機能の作業を修正と一緒に PR に取り込むべきでしょうか?それとも、修正と機能の作業を別々の PR に保つことを好みますか?どちらの方法でも対応できます。レート制限機能は非常にうまく機能しています。sidekiq キューが空になるのを待つようにしたことで、サイトの可用性に影響を与えることなく、約 3 倍の速度でマイグレーションを行っています。したがって、通常 PR で受け入れられるものであれば、取り込むのが妥当だと思います。そうでない場合、それをベースとした作業のマージを待つ必要があります。どちらにせよ、ご意見を聞ければ幸いです。

..

マイグレーションのレート制限パッチを DRY 化し、PR に取り込みました。実際にはうまく機能しており、sar を見ると、ライブマイグレーション中もサイトが機能し続けながら、ほぼゼロのアイドル時間を継続的に確認しています。バッチモードの利点の 1 つは、完全なマイグレーションのバッチごとに新しい Discourse バージョンを確認できることです。2.6.0beta1 がリリースされてすぐに、最初の機会にサイトをアップグレードし、その更新以降、マイグレーション PR を重ねて 2.6.0beta1 で正常にマイグレーションを実行しています。

この PR は現在レビューに提出できる状態だと思います。最後の数段階については別の PR を提出する予定ですが、これを整えることで、最後の部分を完了する前であっても、すべての人の一般的なマイグレーション体験が向上するでしょう。

「いいね!」 5

まあ、それはだいぶ昔の話ですね……

この問題が解決されるのを心から楽しみにしています。現在、マルチサイト環境で複数のサイトを運用しており、S3 から画像を取得する必要があります(現時点では、一部の画像はローカルに、他の画像は S3 上にあると思われます)。その後、それらを S3 へプッシュする予定です。

「いいね!」 1

@pfaffman 移行プロジェクトを始めた当初、今なら理解できているはずのことを知らなかったのは、むしろ幸運だったかもしれません。もし私が minio クライアントを使ってすべての S3 バケットをローカルの uploads フォルダにコピーし、Rails コンソールですべての Upload.urlnil に変更してサイトを再構築していたなら、すべての画像を再生成することなく、数時間で移行が完了していたでしょう。(実際には、すべての画像変換を再度実行しているため、処理速度が制限されています。まるで、S3 から処理済みの画像を単にコピーするよりも、ローカル CPU の方が安価であるかのように。)

そして、もしそれがそれほど簡単だったなら、移行を全般的に信頼性のあるものにするためのこの作業は行われず、他の誰も恩恵を受けなかったでしょう。:smiling_face:

「いいね!」 4

ああ、それは知りたい情報ですね。試してみようかな。

「いいね!」 1

その方法を実行する前に、私は単なる推測に過ぎないため、必ずバックアップを取得しておくことを強くお勧めします。誤解を招きたくありません。

あと一点:音声や動画のアップロードの場合、その方法は完全に失敗してしまい、後になって気づくことになるでしょう。その時点で原因を特定し、カスタムコードを作成する羽目になるはずです。したがって、音声や動画のアップロード機能をお持ちの場合は、まずそこを確認してください。現在オープンになっている PR がマージされない限り正しく動作しません。その PR は @sam 氏によって 2.6 とタグ付けされており、2.5 リリース以降にマージされる予定です。

「いいね!」 2

遅れて会話に参加してしまい、申し訳ありません。あなたの PR を拝見しましたが、なぜ URL を変更するのではなく、Upload モデルを再作成しているのでしょうか?また、OptimizedImages を反復処理して同じことを行うのはなぜでしょうか?

「いいね!」 2

@RGJ その部分は全く変更していません。Upload の再作成は、@zogstrip によるバグ修正で、詳細は Cannot execute the rake uploads:migrate_from_s3 - #11 をご覧ください。

私は単に、元から存在していたコードを動作させようとしているだけで、Discourse の内部構造には詳しくありません。暗闇で手探りしている状態です。私の Ruby に関する経験は、Discourse に対して行った数回の PR に限られています。既存のコードのパターンに従うことが、必ずしも最も効率的な方法ではないことはおっしゃる通りです(上記で @pfaffman と短絡評価について行った会話を参照)。私も完全に同意します。例えば、本日早些く、OptimizedImages.url/uploads パスに変更し、etagnil に設定する必要があることさえ気づいていなかったことからもお分かりいただけるかと思いますが、私はまだ手探りの状態です。

少なくとも、投稿内の古いリテラル URL を修正するためには、まず投稿を反復処理する必要があります。また、投稿の再検証を行わない、エラーを静かに飲み込まない、といった他の修正もまだ必要です。ライブサイトへの影響を制限するため、レート制限も実施したいと考えています。

最初の 2 つの懸念(ポット以外の更新に関連するもの)については、こちらが私の 進行中の作業(まだライブサイトでテスト済みではありません)コミット)です。これがお役に立てるかもしれませんが、投稿のアップロード移行が完了するまで、私のライブサイトでのテストは行いません。

以前動作していたものを調整するのが、私がやる気のある範囲の限界でした。より高速な移行をご希望であれば、大歓迎です。私の「遅いけれど少なくとも改善された」作業をパレート改善としてマージし、その後、それをより優れたものに完全に置き換えるのが合理的かもしれません。その時点で私がそれを利用できなくなっていたとしても、私は真っ先に祝杯を上げることでしょう。

「いいね!」 1

@mcdanlj ご説明いただき、ありがとうございます。私は単に質問をさせていただいただけで、現在問題があることを示唆しているわけではありません。私が提案した方法が本当に「優れている」かどうかはわかりません。むしろ、多くの新たな問題を引き起こすかもしれません。現在のコードは、誰が書いたかに関わらず、何か理由があってそのようになっているのだと思います。

「いいね!」 3

@RGJ 同感です。もし誰かが、すべての画像を再構築するという無駄な作業を避ける方法を確信を持って知っているなら、ぜひとも賛成します。もし私が経験豊富な Discourse 開発者で、それを簡単にできる方法を知っていたなら、最初からそうしていたでしょう。

私の推測では、S3 からの移行は、大量の画像を抱えているユーザーにとって一般的なケースではないため、Discourse により汎用的に役立つ機能を追加する作業に比べて、その価値に見合わない時間がかかるのではないかと思っています。Google+ から MakerForums へ移行した際、約 100GB のアップロードデータがありましたが、多くのユーザーがそれらのコミュニティから MakerForums へ移行する可能性があるという考えから S3 を選択しました。しかし、結局のところ、積極的に移行したコミュニティは数個に留まり、成長が 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.rblib/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"

プロフィールの移行は複雑でした。プロフィールに添付された 2 つのアップロードを移行する必要がありましたが、場合によっては同じ画像を両方に使用していたため、この作業を 3 つの段階で行う必要がありました。私のサイト上のすべてのプロフィールを 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 出力をいじることに時間を無駄にするつもりはありません。

最後に一点:マイグレーション完了後、いくつかのユーザーのプロフィール画像が移行中に失われ、手動で復元していることがわかりました。これを成功させるには追加のコードが必要だったと思われますが、それが遅すぎるまで気づかなかったため、これを検証するテストケースを持っていません。したがって、これは特定の構成で問題を引き起こす可能性のある残存バグですが、私はもはやその追加の修正を書く立場にはありません。

「いいね!」 5

「migrate_from_s3」による静かなデータ破損を修正する私の PR が、少なくとも一瞥もされなかった以上、せめて「migrate_to_s3」は「片道切符」であることをドキュメントに明記してもらえませんか?

現状、正直に言って若手にとっての罠です。

@cvx @zogstrip どちらがお好みですか?PR を確認していただくか、それとも「migrate_from_s3」を完全に削除し、それが片道切符であることを正直に認めるか?

「いいね!」 5

申し訳ありません、私の不手際です。今週中にプルリクエストを確認します。

「いいね!」 7

レビューの内容は、現在の手法が完全に誤っており、ゼロから全く異なる方法で再構築する必要があるというものでした。以前のように修正を試みることは許容できません。私はその覚悟がないため、migrate_from_s3 は完全に削除し、migrate_to_s3 を「元に戻せない一方向の操作」であることを明記すべきだと本気で考えます。現状、migrate_from_s3 がソースコードに残っていること自体が、Discourse におけるデータ整合性の欠陥です。

移行作業中はタイムリーなレビューが得られず、今では移行を完了してしまっています(一部の破損したアバターなど、いくつかの問題が発生しました)。そのため、実用的なテスト環境がなくなっています。私が正しく実施できるとは全く思えないため、この戦いから身を引きました。画像を S3 互換のオブジェクトストレージサービスに格納することで問題を解決しようと考えた、次の不運な担当者に任せるしかありません。申し訳ありません!

「いいね!」 2

@CxV 以前の移行が完全に誤っており、最初からやり直す必要があるとして却下されたため、データ破損バグの除去についてご確認の上、マージをお願いいたします。

「いいね!」 2

既にご指摘の通り、私が行ったマイグレーションでいくつかの問題に直面しました。これは @cvx 氏が「私が完全に誤ったマイグレーションコードを書いた」と指摘した点を裏付けており、誰かが正しい方法で実装するまで、既存のマイグレーション(サイレントなデータ破損を伴うもの)を削除するパッチを 本当にマージすべきです。これは非常にシンプルなパッチであり、レビューは容易であるはずです。早急にマージされれば、ユーザーが片道切符を逆方向に進もうとしてサイトを破壊する可能性は低くなります。マージを強く要請する方法がこれ以上ないとは思いますが、もし思いつけばそうします。編集:承認、マージ、そして大量マイグレーションを「不可逆」としてマークするようフォローアップしてくれた @cvx 氏に感謝します。

以下は、私が直面した既知の問題です:

  • 少なくとも discobot のアバターが表示されませんでした。すべての discobot の参加記録が、一般的な人物アバター(白い背景に薄い灰色の頭と肩)として表示されていました。
  • 他のユーザーのアバターも正しくマイグレーションされませんでした。多くの場合、手動で修正されました。
  • サイト設定中に、元管理者が「S3」設定(当社の場合は CDN あり・なしの Digital Ocean Spaces)の変更を試みたため、マイグレーションで修正されなかった孤立した最適化画像がいくつか残ってしまいました。

私のブランチを試して、このように画像が消失してしまった方へ:Rails コンソールでハックを実行し、いくつかの問題を修正しました。これは正しい方法ではありません。モデルを十分に理解していないため、正しい方法で実装できないだけです。 私の Ruby スキルは非常に弱く、Discourse への小さな貢献以外では Ruby を触ったことがありません。

しかし、このような状態ではありますが、このひどいハックにより、(初期設定ミスによる)破損した画像が修復され、少なくとも discobot のアバター(およびおそらく他のアバターも、ただし以前から問題と認識していたものは既に修復済みでした)が戻ってきました。

ここには示されていませんが、各ステップの間に行われたすべての作業です。これは「Rails コンソールで何が存在するかを探る」セッションの一部であり、実際に私が書いて実行したスクリプトではありません。エラーハンドリングは含まれておらず、この作業を開始する前にサイトの完全なバックアップを取得していました。

このコードが、この修復を行うための Ruby on Rails としての「慣用的な方法」ではないことを、これ以上強く言う方法がわかりません。単に、以前に Digital Ocean Spaces からサイトを移行しようとした際に自分が引き起こした損害の少なくとも一部を、どのように修復したか共有したかっただけです。

require 'set'

uploadids = Set.new
optimizedimages = Set.new
OptimizedImage.where("url like '%UNIQUEPARTOFS3URL%'").each do |oi|
  uploadids.add(oi.upload_id)
  optimizedimages.add(oi)
end

postids = Set.new
uploadids.each do |u|
  PostUpload.where(upload_id: u).each do |pu|
    postids.add(pu.post_id)
  end
end

optimizedimages.each do |oi|
  oi.delete
end

postids.each do |pid|
  Post.where(id: pid).each do |p|
    p.rebake!
  end
end
「いいね!」 2