延迟作业:如何在开发模式下的每次调用期间重新加载有效负载类
Posted
技术标签:
【中文标题】延迟作业:如何在开发模式下的每次调用期间重新加载有效负载类【英文标题】:Delayed job: How to reload the payload classes during every call in Development mode 【发布时间】:2011-06-21 15:53:40 【问题描述】:我正在运行一个延迟工作的工作人员。当我调用foo
方法时,worker 打印hello
。
class User
def foo
puts "Hello"
end
handle_asynchronously :foo
end
如果我对 foo
方法进行一些更改,我必须重新启动工作程序以反映更改。在开发模式下,这可能会变得非常烦人。
我正在尝试找到一种方法来为每个请求重新加载有效负载类(在本例中为用户类)。我尝试猴子修补 DelayedJob 库以在调用有效负载方法之前调用 require_dependency
。
module Delayed::Backend::Base
def payload_object_with_reload
if Rails.env.development? and @payload_object_with_reload.nil?
require_dependency(File.join(Rails.root, "app", "models", "user.rb"))
end
@payload_object_with_reload ||= payload_object_without_reload
end
alias_method_chain :payload_object, :reload
end
这种方法不起作用,因为使用require_dependency
注册的类需要在调用之前重新加载,我还没有弄清楚如何去做。我花了一些时间阅读调度程序代码,以了解 Rails 如何为每个请求重新加载类。我无法找到重新加载代码。
以前有人试过吗?你会建议我如何进行?或者你有任何定位 Rails 类重载代码的指针吗?
【问题讨论】:
【参考方案1】:从 4.0.6 版开始,如果 Rails.application.config.cache_classes
设置为 false
,DelayedJob 会自动重新加载:
在开发模式下,如果您使用的是 Rails 3.1+,您的应用程序代码将每 100 个作业或队列完成时自动重新加载。您不再需要在每次更新开发中的代码时重新启动延迟作业。
【讨论】:
【参考方案2】:这看起来可以在没有 alias_method 黑客的情况下解决您的问题:
https://github.com/Viximo/delayed_job-rails_reloader
【讨论】:
【参考方案3】:我设法找到了解决方案。我使用ActiveSupport::Dependencies.clear
方法清除加载的类。
添加一个名为config/initializers/delayed_job.rb
的文件
Delayed::Worker.backend = :active_record
if Rails.env.development?
module Delayed::Backend::Base
def payload_object_with_reload
if @payload_object_with_reload.nil?
ActiveSupport::Dependencies.clear
end
@payload_object_with_reload ||= payload_object_without_reload
end
alias_method_chain :payload_object, :reload
end
end
【讨论】:
谢谢!这很好用,即使使用 mongoid 作为后端。我只需要删除第一行就可以了:) 不错!做了类似的事情,但作为separate script 并与foreman 一起使用 我不太明白为什么,但这会导致我的 Rails 内存在所有环境(包括生产环境)和非 DJ 实例中爆炸。以上是关于延迟作业:如何在开发模式下的每次调用期间重新加载有效负载类的主要内容,如果未能解决你的问题,请参考以下文章