class Olt < ActiveRecord::Base
has_many :gpon_olts
end
class GponOlt < ActiveRecord::Base
belongs_to :olt
has_many :onus
end
class Onu < ActiveRecord::Base
belongs_to :gpon_olt
end
W tasku zmieniłem:
Olt.where(online: true).each do |olt|
...
gpon_olts = []
olt.gpon_olts.each do |o|
gpon_olts << o.id
end
...
Na:
Parallel.each(Olt.where(online: true), :in_threads => 4) do |olt|
I raz na jakiś czas (task jest uruchamiany co kilka minut, zawartość Olt i GponOlt się nie zmienia) wywala mi exception:
Circular dependency detected while autoloading constant GponOlt
w linii:
olt.gpon_olts.each do |o|
Co to jest za błąd i o czym on mówi?
PS. Przed zmianą na Parallel taki błąd nie występował.
Problemem jest to, że mechanizm autoloadingu klas w railsach nie jest threadsafe. W jakim środowisku odpalasz ten task? W środowisku production jest włączony eager loading (czyli ładowanie plików przed startem aplikacji) i ten problem nie powinien występować. Zakładam więc, że ten błąd dostajesz w środowisku dla którego eager loading masz wyłączony.
W trakcie pisania tej odpowiedzi zerknąłem na przykładowy plik config/environments/production.rb i znalazłem coś takiego:
Eager load code on boot. This eager loads most of Rails and
your application in memory, allowing both threaded web servers
and those relying on copy on write to perform better.
Rake tasks automatically ignore this option for performance.
config.eager_load = true
A to ci niespodzianka, człowieka uczy się całe życie :). Jak rozwiązać ten problem? Szczerze mówiąc nie przychodzi mi nic innego do głowy jak ręczne załadowanie modeli w tym wielowątkowym tasku:
require "olt"
require "gpon_olt"
require "onu"
# do dzieła