マルチスレッド環境下での「RuntimeError: Circular dependency detected while autoloading constant xxxx」を解消した話

  • 16
    いいね
  • 2
    コメント
この記事は最終更新日から1年以上が経過しています。

検証環境

  • Rails 4.1.5
  • sidekiq 3.3.2

事象

sidekiqでマルチスレッド処理を実行中に、autoload_pathにアクセスしたところ、下記のエラーが発生

    Circular dependency detected while autoloading constant Lib::MyConstant

原因

これかな。。。?

constant autoloading works fine if constants are loaded in a sequential way. I have never seen a problem with constant autoloading that didn't uncover something wrong in the application code.

定数のautoloadingは定数がシーケンシャルにロードされる時は正常に動作する。

ここによると、

If code is not eager loaded constants are loaded on demand. Constant
autoloading is not thread-safe, so if eager loading is not enabled
multi-threading should not be allowed.

eager_loadされていない定数は、必要に応じてloadされる。定数のautoloadingはthread-safeではない。
従って、eager loadingが有効になっていない場合はmulti-threadingは許容されない。

Rails・マルチスレッド環境で「RuntimeError: Circular dependency detected while autoloading constant xxxx」が発生する

対応

autoload_pathsではなく、eager_load_pathsを使用するように変更してみた。

検証用スクリプト

namespace :test do
  desc 'autoload with multi thread.'
  task autoload_multithread: :environment do

    t1 = Thread.new { Lib::MyConstant }
    t2 = Thread.new { Lib::MyConstant }

    t1.join
    t2.join

  end
end

変更前

  config.autoload_paths += %W(#{config.root}/lib/)

検証スクリプトでエラーが発生することを確認

変更後

  config.eager_load_paths += %W(#{config.root}/lib/)

eager_loadを使用して、事象が解消する事を確認できた!

参考資料