Upgrade to Pro — share decks privately, control downloads, hide ads and more …

configの設定をちょっと変えたら Autoloading and Reloadingのエラーに 思いっきりハマってしまった話

Yuta Fujii
May 21, 2021
34

configの設定をちょっと変えたら Autoloading and Reloadingのエラーに 思いっきりハマってしまった話

configの設定をちょっと変えたら
Autoloading and Reloadingのエラーに
思いっきりハマってしまった話

Yuta Fujii

May 21, 2021
Tweet

Transcript

  1. Yuta Fujii RailsはAutoloadingとReloadingのために何をしたのか? 未知の定数に遭遇 → NameError まず推論 ファイル修正 → 反映されない 必要に応じてリロード Reloading

    • これまでにない処理がある=メソッドの追加 ◦ consoleでのreload!メソッド ◦ Serverでのreload & autoloadのメカニズム(後述)
  2. Yuta Fujii module Admin class BooksTagsController def create @tagging =

    BookTag.new # … end end end 開発環境でブラウザからアプリを開く時,何が起きている? ClientがHTTPリクエスト routingがあるか探索 対応するコントローラーを探索 処理が実行,レスポンス
  3. Yuta Fujii controller_name = ‘admin/books_tags_controller’ controller_name.constantize # => Admin::BooksTagsController Autoloadingの仕組み

    ClientがHTTPリクエスト routingがあるか探索 対応するコントローラーを探索 ない場合は const_missingメソッド発火 autoload_pathから定義を探索 ”Admin::BooksTagsController” 定数を取得しようとする
  4. Yuta Fujii module Admin class BooksTagsController def create @tagging =

    BookTag.new # … end end end Autoloadingの仕組み ClientがHTTPリクエスト routingがあるか探索 対応するコントローラーを探索 処理が実行,レスポンス ”BookTag” 定数を取得しようとする ない場合は const_missingメソッド発火 autoload_pathから定義を探索
  5. Yuta Fujii Reloadingの仕組み ClientがHTTPリクエスト routingがあるか探索 対応するコントローラーを探索 処理が実行,レスポンス 終了 修正ファイルをunload unload対象の定数もリストから削除

    ない場合は const_missingメソッド発火 autoload_pathから定義を探索 ”Admin::BooksTagsController” 定数を取得しようとする ”BookTag” 定数を取得しようとする ない場合は const_missingメソッド発火 autoload_pathから定義を探索 先に定数リストから修正入ったものを削除しておくことで const_missingを発火する ようにしておく
  6. Yuta Fujii 正直メッセージの内容がわかりづらい “A copy of Foo has been removed

    from the module tree but is still active!” どゆこと? ME “A copy of Foo has been removed from the module tree but is still active!” ... ME
  7. Yuta Fujii レベルアップしていくエラー “A copy of Foo::Api has been removed

    from the module tree but is still active!” え,君も!?てかこれどこ? ME “A copy of Foo::Api::Some has been removed from the module tree but is still active!” さっきと微妙に違う... ME
  8. Yuta Fujii config.reload_classes_only_on_change = false の場合 reload_classes_only_on_change = falseだと ClientがHTTPリクエスト

    routingがあるか探索 対応するコントローラーを探索 処理が実行,レスポンス 終了 リスエスト処理が完了するたびに 次のリクエストで都度定数を全削除してしまう
  9. Yuta Fujii その結果 ClientがHTTPリクエスト routingがあるか探索 対応するコントローラーを探索 ClientがHTTPリクエスト routingがあるか探索 対応するコントローラーを探索 GET

    /api/books GET /api/tags Vueインスタンス created() ほぼ同時にリクエストが 2本送られる Subdomain::Api::BooksController Subdomain::Api::TagsController remove_const remove_const config.reload_classes_only_on_change = false なのでリクエストの度にここでほぼ全ての定数が削除
  10. Yuta Fujii その結果 → race condition ClientがHTTPリクエスト routingがあるか探索 対応するコントローラーを探索 ClientがHTTPリクエスト

    routingがあるか探索 対応するコントローラーを探索 GET /api/books GET /api/tags Vueインスタンス created() ほぼ同時にリクエストが 2本送られる Subdomain::Api::BooksController Subdomain::Api::TagsController remove_const remove_const Subdomain::Api::BooksControllerが missing_constを引き起こし 順次Moduleオブジェクトを作っていく. (Subdomain, Subdomain::Api, Subdomain::Api::BooksController) 各Moduleオブジェクト作成途中に 2本目のリクエストで必要な Subdomain::Api::BooksControllerが missing_constを引き起こし, 同じModuleのオブジェクトが2個できてしまう
  11. Yuta Fujii 余談 Dog オブジェクト Object オブジェクト Class オブジェクト Is

    instance of Is instance of Is inherited from name: ‘Object’ constants:[:Dog, ..etc.] 定数とクラスと名前の話. 右の1行がインタプリタによって処理されるとき, Classクラスのインスタンスである Dogクラスオブ ジェクトが作成される. 基本的に作成されるクラスは Objectクラスを継承 しており,Dogクラスも同様となる. Objectクラスのconstantsに :Dogが追加される. 定数DogにはDogクラスのオブジェクトが対応す る. constantとしてのDogと,Classクラスのオブジェク トであるDogクラスと,Dogクラスというオブジェクト に備わっているnameメソッド(Moduleクラスのメ ソッド)の戻り値になる ’Dog’の区別を意識するの はなかなか難しい. Is instance of name: ‘Dog’ constants:[] name: ‘Class’ constants:[]
  12. Yuta Fujii 参考 RAILS GUIDES https://guides.rubyonrails.org/autoloading_and_reloading_constants_classic_mode.html https://guides.rubyonrails.org/autoloading_and_reloading_constants.html Rails GitHub https://github.com/rails/rails/blob/main/activesupport/lib/active_support/dependencies.rb

    https://github.com/rails/rails/blob/main/activesupport/lib/active_support/inflector/methods.rb Rails Issue https://github.com/rails/rails/issues/33209 Zeitwerk GitHub https://github.com/fxn/zeitwerk#pronunciation バグ検証メモ https://zenn.dev/yutafujii/scraps/cd5500cd468a39