初始化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
答案 0 :(得分: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