4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ユニークビジョン株式会社Advent Calendar 2018

Day 9

Rails アプリを eager_load! してみることでプロダクション環境での出落ちを未然に防ぐ

Last updated at Posted at 2018-12-08

環境

Rails 5.2.1.1

デプロイしたら Rails が出落ちした

ある日いつものように Rails アプリをデプロイすると、未定義の module を include しようとしていたことが原因で Rails がアプリケーションの読み込みに失敗し、uninitialized constant ... (NameError) を吐いてクラッシュしてしまいました。

開発環境では動いたんだけど…

本番またはステージング環境では、開発環境と違って環境毎の設定ファイルに

config/environments/production.rb
config.eager_load = true

と書くことで Rails が起動時にアプリ全体を読み込むように設定すると思いますが、このときアプリ全体に少しでも読み込みに失敗するようなコードがあると Rails はクラッシュしてしまいます。

今回はデプロイ前に RuboCop の警告がないことを確認し、RSpec による単体テストを通してはいましたが、該当部分を通るテストケースがなかったために、読み込めないソースコードが存在することに気づくことができませんでした。

出落ちを未然に防いだ

単体テストが Rails アプリの全てのコードが読み込まれる程度にはしっかり書かれているのが理想ですが、完璧に網羅し続ける自信はありません。そこで、CI の Job に以下のコマンドを追加し、CI パイプライン内で Rails がアプリケーションの読み込みでエラーを起こさないことを確認するようにしました。

bundle exec rails runner Rails.application.eager_load!

これでデプロイ前に、少なくとも Rails が読み込みに失敗するようなコードが無いことを CI で保証できるようになりました。別のアプローチとして、以下のようにテスト時に環境変数で eager_load を行うかを流し込めるようにするアプローチも見つけました1 が、テストケースの失敗とアプリケーションの読み込みの失敗を分けて把握したかったので、一旦上のような形に落ち着きました。

config/environments/test.rb
config.eager_load = ENV.fetch('EAGER_LOAD', '0') == '1'
  1. https://github.com/rails/rails/issues/28736#issuecomment-293822999

4
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?