DelayedJob Worker не настроен инициализаторами рельсов - PullRequest
0 голосов
/ 21 февраля 2019

Как правильно инициализировать состояние приложения rails, чтобы на эту инициализацию влияли работники DelayedJob (а также приложение rails)? У меня возникают проблемы при настройке конфигурации приложения вмои инициализаторы rails, кажется, не видны для моих заданий DelayedJob.

У меня есть несколько наблюдаемых / синглетов 'service', которые я организовываю в инициализаторе rails, как (это надуманный пример):

# my_app_initializer.rb
puts 'initializing my app...' # this DOES get logged in DJ worker

ShopActivityService.instance.add_observer(NotificationService.instance, func=:handle_shop_activity)

# if someone calls ShopActivityService.do_activity(), notification service sends an email

Идея состоит в том, что всякий раз, когда происходит какая-либо «активность в магазине», «служба уведомлений» отправляет электронное письмо или что-то в этом роде.

Проблема заключается в в том, что при задержке работырабочий вызывает ShopActivityService, служба NotificationService, по-видимому, не зарегистрирована в качестве наблюдателя и поэтому не получает уведомления.

Я заметил, что инициализатор вызывается, когда я запускаю приложение с rails jobs:work,но код в самом задании должен быть запущен из какой-либо другой среды или контекста?

edit: simpЕще один способ демонстрации проблемы:

# my_job.rb
class MyJob
  @@x = 0
  def self.inc_x
    @@x = @@x + 1
  end
  def self.print_x
    puts "x is #{@@x}"
  end

  def self.schedule_job
    new.delay.execute_job
  end

  def execute_job
    self.class.print_x
  end
end

# my_job_initializer.rb
MyJob.inc_x

, затем в rails console это приводит к неожиданным результатам:

MyJob.print_x
# prints 'x is 1' as expected

MyJob.schedule_job
# the delayed job worker process prints 'x is 0'

edit 2: Я задал этот вопросв DJ group и создали небольшой проект github, демонстрирующий проблему: https://github.com/cechner/dj_test

1 Ответ

0 голосов
/ 23 февраля 2019

Помог мне добрый плакат в группе отложенных заданий: https://groups.google.com/forum/#!topic/delayed_job/hgZvJtydLWs

Подводя итог, rails в режиме разработки по умолчанию выполняет «перезагрузку кода» для всего кода, работающего в каталоге app/.Однако он не перезагружает код в каталоге config/initializers/.Таким образом, мои службы перезагружались (и, следовательно, наблюдатели очищались), но инициализация, которая управляет этими службами (путем регистрации наблюдателей), не выполнялась повторно.

Мне известно о проблеме с использованием синглетоновподелиться глобальным состоянием, но я не уверен, что «правильный» или одобренный сообществом подход для управления сервисами во время выполнения.

На данный момент я решил проблему с помощью следующего:

# config/initializers/my_application_config.rb
module MyApplication
  class Application < Rails::Application
    # was previously doing config.after_initialize, but to_prepare seems to be called every time a reload happens
    config.to_prepare do
      ServiceOrchestrator.prepare
    end
  end
end

# app/services/service_orchestrator.rb
class ServiceOrchestrator
  def self.prepare
    # clear because this seems to be invoked twice every reload for some reason
    ShopActivityService.instance.delete_observers

    ShopActivityService.instance.add_observer(NotificationService.instance, func=:handle_shop_activity)
  end
end
...