バックアップから SVG ファイルを復元する際のバグ

バックアップの復元を試みると(マルチサイト向けですが、後述するようにそれは関係ないようですが)、以下のようなエラーが発生します。

Migrating the database...
EXCEPTION: lib/discourse.rb:57:in `exec': Failed to migrate database.
rake aborted!
Errno::ENOENT: No such file or directory @ rb_sysopen - /var/www/discourse/public/uploads/default/original/2X/7/7be997f9f48c034ddf5d4eb95d2ea7416f010241.svg
/var/www/discourse/app/models/optimized_image.rb:87:in `block in create_for'
/var/www/discourse/app/models/optimized_image.rb:24:in `block (2 levels) in lock'
/var/www/discourse/lib/distributed_mutex.rb:33:in `block in synchronize'
/var/www/discourse/lib/distributed_mutex.rb:29:in `synchronize'
/var/www/discourse/lib/distributed_mutex.rb:29:in `synchronize'
/var/www/discourse/lib/distributed_mutex.rb:14:in `synchronize'
/var/www/discourse/app/models/optimized_image.rb:23:in `block in lock'
/var/www/discourse/lib/distributed_mutex.rb:33:in `block in synchronize'
/var/www/discourse/lib/distributed_mutex.rb:29:in `synchronize'
/var/www/discourse/lib/distributed_mutex.rb:29:in `synchronize'
/var/www/discourse/lib/distributed_mutex.rb:14:in `synchronize'
/var/www/discourse/app/models/optimized_image.rb:22:in `lock'
/var/www/discourse/app/models/optimized_image.rb:59:in `create_for'
/var/www/discourse/lib/site_icon_manager.rb:28:in `block in ensure_optimized!'
/var/www/discourse/lib/site_icon_manager.rb:24:in `each'
/var/www/discourse/lib/site_icon_manager.rb:24:in `ensure_optimized!'
/var/www/discourse/lib/tasks/db.rake:83:in `block in <top (required)>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/exe/rake:27:in `<top (required)>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/bin/ruby_executable_hooks:24:in `eval'
/var/www/discourse/vendor/bundle/ruby/2.6.0/bin/ruby_executable_hooks:24:in `<main>'
Tasks: TOP => db:migrate

当初、これは純粋なマルチサイト関連の問題だと考えましたが、マルチサイトではない環境でも同様に失敗します。

面白いことに、その時点ではアップロードファイルの展開すら行われていませんでした(編集:その時点では)。ただし、その特定のアップロードファイルはアーカイブに含まれています。

tar tvf public/backups/default/redacted-forum-2020-03-02-165725-v20190130013015.tar.gz |grep 7be997f9f48c034ddf5d4eb95d2ea7416f010241
-rw-r--r-- daemon/daemon     3074 2019-05-27 08:21 uploads/default/original/2X/7/7be997f9f48c034ddf5d4eb95d2ea7416f010241.svg

元のデータベースダンプのバージョンは v20190130013015 です。

その後、アップロードファイルを手動で展開(default 配下へ)し、再度復元を実行したところ、成功しました。

そして気づきました…アップロードファイルの展開は db:migrate の後に行われますが、db:migrate はすでにファイルが存在することを前提として SiteIconManager.ensure_optimized! を実行しているのです…

つまり、以下の 2 つの問題があります:

  • SiteIconManager.ensure_optimized! が画像の展開前に実行される(実際には 2 回実行されます。1 回は画像の展開後にもう一度実行されます)。
  • リマップがまだ実行されていないため、ファイルが default 配下にあることを想定している。

この特定のケースでは、SVG アップロードの処理コードが 異なるコードパス をたどるため、明確に失敗します。他のアップロードファイルの場合は、静かに失敗しているようです。

余談ですが、コードを確認すると、SKIP_POST_DEPLOYMENT_MIGRATIONS=1 を使用することで回避できる可能性があります。これは db:migrate 中の画像最適化をスキップするためですが、試したところ効果はありませんでした。

「いいね!」 6

@sam さん、これは誰が確認すべきでしょうか?

「いいね!」 1

かなりシンプルに見えますね:

そして

このフローに最後に触れたのは @gerhard さんです。

@RGJ もし診断を迅速に行いたい場合は、復元に失敗する単一の SVG を含む空のデータベースを作成してみてください。そうすれば、私たちのテストが格段に簡単になります。

「いいね!」 7

最小限のバックアップファイルをPMで送付しましたが、復元されません。

バグをトリガーするには、favicon または manifest に「小さな」SVG ファイルが必要です。

追伸:SKIP_POST_DEPLOYMENT_MIGRATIONS が明示的に リセット されていることを最近知りました。そのため、回避策として機能しませんでした。

「いいね!」 5

ご報告とサンプルファイルの提供、ありがとうございます。修正済みです。

「いいね!」 6