DelayedJob Worker未由rails初始化程序配置

问题描述 投票:1回答:1

初始化rails应用程序状态的正确方法是什么,以便DelayedJob工作程序(以及rails应用程序)受初始化影响?我遇到问题,我的rails初始化程序中设置的应用程序配置似乎对我的DelayedJob作业不可见。

我有几个'服务'可观察/单例,我在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启动应用程序时调用初始化程序,但作业本身的代码必须从其他一些环境或上下文运行?

编辑:演示问题的简单方法:

# 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'

编辑2:我在DJ group上问过这个问题并创建了一个小github项目来证明这个问题:https://github.com/cechner/dj_test

ruby-on-rails delayed-job
1个回答
0
投票

延迟工作小组的一张亲切的海报帮助了我: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
© www.soinside.com 2019 - 2024. All rights reserved.