2021-06-11 Rails とマルチスレッド
Railsガイドにマルチスレッドの扱い方に関して記述がある。
Rails のスレッドとコード実行 - Railsガイド
アプリケーションのコードを呼び出す何らかのライブラリやコンポーネントを書く場合は、次のようにexecutor呼び出しでラップすべきです。
Thread.new do
Rails.application.executor.wrap do
# ここにコードを書く
end
end
デフォルトのRailsアプリケーションでは、Executorのコールバックを以下の用途に用います。
- 自動読み込みや再読み込みを安全に行えるスレッドがどれかをトラッキングする
- Active Recordクエリキャッシュをオン/オフする
- 獲得したActive Recordコネクションをコネクションプールに返す
- 内部キャッシュの寿命を制限する
外側のスレッドは
permit_concurrent_loads
メソッドを呼び出すことでこのデッドロックを防げます。このメソッドを呼ぶと、提供されたブロック内で自動読み込みされた可能性のある定数をそのスレッドが参照解決しないことが保証されます。この保証に合致する最も安全な手法は、このメソッド呼び出しを、可能な限りブロッキングされる呼び出しの近くに配置することです。
Rails.application.executor.wrap do
th = Thread.new do
Rails.application.executor.wrap do
User # 内側のスレッドは'load'ロックを取得し
# Userを読み込んで続行できる
end
end
ActiveSupport::Dependencies.interlock.permit_concurrent_lo> ads do
th.join # 外側のスレッドはここで待機するがロックを保持しない
end
end