私はRailsタスクを持っており、Railsタスクはconcurrent-ruby gemによって提供されるマルチスレッド機能を使用しています。Railsでのマルチスレッド:自動ローディング中に循環依存関係が検出されました
時々私はCircular dependency detected while autoloading constant
エラーが発生します。
ちょっとグーグルで調べたところ、これはRails定数の読み込みと組み合わせてスレッディングを使用することに関連していることがわかりました。私は、次のGitHubの問題につまずい
:https://github.com/ruby-concurrency/concurrent-ruby/issues/585とhttps://github.com/rails/rails/issues/26847
として、あなたは私が何をしたかであるRails.application.reloader.wrap do
またはRails.application.executor.wrap do
ブロックで新しいスレッドから呼び出された任意のコードをラップする必要があり、ここで説明しました。しかし、これはデッドロックにつながります。
ActiveSupport::Dependencies.interlock.permit_concurrent_loads
を使用して、メインスレッドで別のブロッキングコールをラップすることをお勧めします。しかし、私はこのコードをどのコードで囲むべきかは不明です。
は、ここに私が試したものだが、これはまだデッドロックにつながる:
@beanstalk = Beaneater.new("#{ENV.fetch("HOST", "host")}:#{ENV.fetch("BEANSTALK_PORT", "11300")}")
tube_name = ENV.fetch("BEANSTALK_QUEUE_NAME", "queue")
pool = Concurrent::FixedThreadPool.new(Concurrent.processor_count * 2)
# Process jobs from tube, the body of this block gets executed on each message received
@beanstalk.jobs.register(tube_name) do |job|
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
@logger.info "Received job: #{job.id}"
Concurrent::Future.execute(executor: pool) do
Rails.application.reloader.wrap do
# Stuff that references Rails constants etc
process_beanstalk_message(job.body)
end
end
end
end
@beanstalk.jobs.process!(reserve_timeout: 10)
誰もが、私はこの問題を解決する方法のように、光を当てることができますか?奇妙なことに私は生産でこれに遭遇していますが、このトピックに関する他の情報は、それが通常開発中にのみ起こるべきであることを暗示しているようです。
config.eager_load = true
config.cache_classes = true
:
は、生産では、私は次の設定を使用します。
すべての環境の自動ロードパスは、Railsのデフォルトと2つの特定のフォルダ( "モデル/バリデータ" & "jobs/concerns")です。
eager_load_paths
は、私の設定で変更または設定されていないので、Railsのデフォルトと同じでなければなりません。
私はRails 5を使用していますので、enable_dependency_loading
はfalse
と同じにする必要があります。
どのRails環境でこれを試してもエラーが発生しましたか?これらの環境の 'eager_load_paths'と' autoload_paths'とは何ですか? (通常は 'config/application.rb'と' config/environments/*。rb'にあります) – anothermh
ああ - 私は@anothermhと同じ質問をしようとしていました。あなたのapplication.rbでは、私はあなたがこれらの2つのセットのいずれかを持っていると思っています。 ' config.enable_dependency_loading = false'でオートローディングを無効にすると役立ちます。 – stef
@anothermh修正回答をご覧ください。プロダクションのためにパスを自動ロードしないでください(たとえば、この設定をapplication.rbではなくdevelopment.rbに入れてください)。循環依存性エラーメッセージに含まれる定数は、それらの 'autoload_paths'で定義されていないことに注意してください。 – edwardmp