序
rails5にて。
とある、パラレル処理を行っているコントローラーがあった。
イメージ
...
Parallel.each(records, :in_threads=>4) do |r|
Blablabla::BullshitService.new(r.dead_beaf).bullshit
end
...
リファクタのためにrspecでrequestsのテストを書いていたら、実行時に
No live threads left. Deadlock?
というエラーになって失敗した。
イメージ
$ bundle exec rspec spec/requests/api/blablabla_controller_spec.rb
...
fatal - No live threads left. Deadlock?
4 threads, 4 sleeps current:0x000055d836b087e0 main thread:0x000055d82d7f48e0
* #<Thread:0x000055d82e208c88 sleep_forever>
rb_thread_t:0x000055d82d7f48e0 native:0x00007ff40e623b68 int:1
/bundle/gems/parallel-1.18.0/lib/parallel.rb:212:in `value'
/bundle/gems/parallel-1.18.0/lib/parallel.rb:212:in `map'
/bundle/gems/parallel-1.18.0/lib/parallel.rb:212:in `block (2 levels) in in_threads'
/bundle/gems/parallel-1.18.0/lib/parallel.rb:211:in `handle_interrupt'
/bundle/gems/parallel-1.18.0/lib/parallel.rb:211:in `block in in_threads'
/bundle/gems/parallel-1.18.0/lib/parallel.rb:204:in `handle_interrupt'
/bundle/gems/parallel-1.18.0/lib/parallel.rb:204:in `in_threads'
/bundle/gems/parallel-1.18.0/lib/parallel.rb:353:in `work_in_threads'
/bundle/gems/parallel-1.18.0/lib/parallel.rb:275:in `map'
/bundle/gems/parallel-1.18.0/lib/parallel.rb:227:in `each'
...
app/controllers/api/blablabla_controller.rb:66:in `bullshit'
(0.6ms) ROLLBACK
F
破
gemのparallelのどこかで不具合が起きているのかなと思いgem側のissueを確認した。
それっぽいのはあるが、自分のケースとはちがった。
ソースを確認しても、怪しそうなところの検討がつけられなかった。
(泣きながら)1つの処理しか並行動作しないようにしつつ binding.pry
をかけて、stepで潜り始めたところ
すぐ次のようなframeにぶち当たり
200: def const_missing(const_name)
=> 201: from_mod = anonymous? ? guess_for_anonymous(const_name) : self
202: Dependencies.load_missing_constant(from_mod, const_name)
203: end
railsのautoload のことを思い出す。
RAILS_ENV=production時は eager_load によって起動シーケンスですべてのクラスがロードされるが
test, developmentなどのときはautoloadにて都度読み込まれている。
rspecの該当箇所付近にてeager_load!
を呼ぶようにしたところ、エラーが起こらなくなった。
Rails.application.eager_load!
Parallel.each
の各blockにて、それぞれautoloadが起こって競合している模様。
autoloadの仕組みはthread-safeではなかったのか、、
テスト時に全部ロードするのはなんだか嫌だけど、requireを都度書くのも保守したくなくなりそう。
ベストプラクティスが知りたい。
急
_人人人人人人人人人人人人_
> pryつかいにくくない? <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄
see also
Rails 5 disables autoloading while app in production
https://blog.bigbinary.com/2016/08/29/rails-5-disables-autoloading-after-booting-the-app-in-production.html