延迟任务:如何在开发模式下每次调用重新加载有效载荷类

14

我正在运行一个延迟的任务工作者。每当我调用foo方法时,工作者会输出hello

class User
  def foo
    puts "Hello"
  end
  handle_asynchronously :foo
end

如果我对foo方法进行更改,则必须重新启动工作进程才能反映更改。在开发模式下,这可能会变得非常烦人。

我正在尝试找到一种方法,在每个请求中重新加载负载类(在本例中为User类)。 我尝试使用Monkey Patching 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类重新加载代码的指针吗?

3个回答

20

我找到了解决办法。我使用了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

1
谢谢!这个很好用,即使使用Mongoid作为后端也可以。我只需要删除第一行就可以了 :) - Derick Bailey
不错!我做了类似的事情,但是作为一个单独的脚本并与foreman一起使用。 - Mattias Wadman
我不是很明白为什么,但这会导致我的Rails内存在所有环境(包括生产环境)和非DJ实例中崩溃。 - Mike Atlas

1
从版本4.0.6开始,如果将设置为,DelayedJob会自动重新加载:

在开发模式下,如果您使用的是Rails 3.1+,则应用程序代码将在每100个作业或队列完成时自动重新加载。您无需在开发中每次更新代码时重新启动Delayed Job。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接