Delayed_job 不执行 perform 方法但清空作业队列

Posted

技术标签:

【中文标题】Delayed_job 不执行 perform 方法但清空作业队列【英文标题】:Delayed_job not executing the perform method but emptying the job queue 【发布时间】:2011-05-31 22:31:22 【问题描述】:

我有一个新的 rails 3 应用,这是我的 Gemfile:

source 'http://rubygems.org'
gem 'rails', '3.0.0' gem 'delayed_job'
gem 'sqlite3-ruby', :require => 'sqlite3'

这是代表我要排队的作业的类:

class Me < Struct.new(:something)
   def perform
     puts "Hello from me"
     logger.info "Hello from me"
     logger.debug "Hello from me"
     raise Exception.new   
   end
end

从没有工人运行的控制台:

irb(main):002:0> Delayed::Job.enqueue Me.new(1)
=> #<Delayed::Backend::ActiveRecord::Job id: 7, priority: 0, attempts: 0, handler: "--- !ruby/struct:Me \nsomething: 1\n", last_error: nil, run_at: "2010-12-29 07:24:11", locked_at: nil, failed_at: nil, locked_by: nil, created_at: "2010-12-29 07:24:11", updated_at: "2010-12-29 07:24:11">

就像我提到的:没有工人在运行:

irb(main):003:0> Delayed::Job.all
=> [#<Delayed::Backend::ActiveRecord::Job id: 7, priority: 0, attempts: 0, handler: "--- !ruby/struct:Me \nsomething: 1\n", last_error: nil, run_at: "2010-12-29 07:24:11", locked_at: nil, failed_at: nil, locked_by: nil, created_at: "2010-12-29 07:24:11", updated_at: "2010-12-29 07:24:11">]

我用script/delayed_job run开始一个工人

队列被清空:

irb(main):006:0> Delayed::Job.all
=> []

但是,puts 不会导致任何事情发生,logger 调用不会记录任何内容,并且不会引发异常。我将不胜感激任何帮助/见解或任何尝试。

【问题讨论】:

我遇到了完全相同的问题。你有没有解决过这个问题? 【参考方案1】:

默认情况下,delayed_job 会销毁失败的作业:

所以第一步是配置初始化程序并停用该行为

Delayed::Worker.destroy_failed_jobs = false  

此外,如果您遇到反序列化失败,那么这就是即时作业失败。

这会触发作业删除(如果您尚未删除它)。

所以尝试在 worker.rb 的第 120 行附近添加以下内容

rescue DeserializationError => error
  say "DeserializationError: #error.message"
  job.last_error = "#error.message\n#error.backtrace.join('\n')"
  failed(job)

这没什么用,但至少你会知道这是一个反序列化错误。

我最终只使用了 w 的工作。 perform() 方法构造。可靠得多。还要记住将你的作业定义作为一个单独的文件,这样类加载器可以在它运行时找到它(而不是仅仅将类定义内联到你的模型中的某个地方)。

【讨论】:

【参考方案2】:

Ben W 是绝对正确的,确保你有一个文件

"#Rails.root/config/initializers/delayed_job_worker.rb"

这定义了工人的行为方式。否则,工作人员将悄悄地删除错误。

执行此操作后,您应该能够了解有关您的错误的更多信息。对于我的例子,我使用了delayed_job_mongoid,所以这添加了一个“last_error”条目(我认为你应该在你的mysql表中为delayed_job添加一个条目......)

正如 Ben W 总结的那样,您需要确保应用程序(或工作人员)知道您正在创建的对象。我的问题是我在 Rails 控制台中测试一个类对象。工人不知道这个类,所以它吐了。

在我的 application.rb 文件中:

module TextSender
  class Application < Rails::Application
    require "#Rails.root.to_s/lib/SendTextJob.rb"

还有我的 lib 文件:

class SendTextJob < Struct.new(:text, :number)
  def perform
    Rails.logger.info "Sending #text to #number"
    puts "Successfully sent text"
  end
end

然后运行

Delayed::Job.enqueue SendTextJob.new("Work on this text NOW, please?", "5551231234")

在我的 log/development.log 文件中确认这是成功的。我还在这个 perform 方法中测试了创建和对象(用户对象或任何你可能拥有的模型),并且它有效。

【讨论】:

【参考方案3】:

我遇到了这个问题,我发现这是因为在 Rails 3 中lib/ 目录中的文件没有自动加载。为了诊断,我补充说:

# application.rb
Delayed::Worker.destroy_failed_jobs = false

正如 Ben W 所提到的。这告诉了我发生了什么,因为我可以检查 last_error

所以为了解决自动加载问题,我在 SO 上找到了几个答案,但要点是添加:

# application.rb

# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#config.root/extras)
config.autoload_paths += %W(#config.root/lib)
config.autoload_paths += Dir["#config.root/lib/**/"]

由http://hemju.com/2010/09/22/rails-3-quicktip-autoload-lib-directory-including-all-subdirectories/提供。

我很想知道如何在不为 lib 目录打开自动加载的情况下解决这个问题。有什么想法吗?

【讨论】:

【参考方案4】:

我刚刚将你的课程复制到 irb 并尝试做Me.new.perform

Hello from me
NameError: undefined local variable or method `logger' for #<struct Me something=nil>
from (irb):6:in `perform'
from (irb):14

您的班级是否可以访问“记录器”?

您可以尝试做其他事情,例如打开和写入文件?

File.open("testing.txt", 'w') |f| f.write("hello") 

请记住,延迟作业工作者的“puts”命令将输出到 标准输出,因此您可能永远不会看到这一点。如果你想做任何日志记录,我认为你必须在你的 perform 方法中创建一个新的 Logger 实例才能这样做。

【讨论】:

我尝试删除记录器调用并按照您的描述写入文件。我仍然看到相同的行为 - 作业从队列中删除,但文件没有被写入。【参考方案5】:

你运行的是什么版本的delayed_job?

对于 Rails 3.0 及更高版本,您需要位于 https://github.com/collectiveidea/delayed_job 的 2.1 分支。

【讨论】:

是的,它是我认为是 2.1 的主分支【参考方案6】:

检查日志,您应该会看到有关 DelayedJob 消息,至少启动了哪个作业以及它的退出状态是什么

在终端中,启动:

tail -f log/development.log

然后从 Rails 控制台重试以检查执行简单的 ActiveRecord 查询会发生什么,然后使用 DelayedJob。您可以阅读其他终端上记录的内容

干杯, A.

【讨论】:

以上是关于Delayed_job 不执行 perform 方法但清空作业队列的主要内容,如果未能解决你的问题,请参考以下文章

当 ActionMailer 遇到错误时,如何让 Delayed_Job 通知 Airbrake?

Delayed_job - 多个并行队列?

Heroku 上的 Delayed_Job 显示“禁止”错误

英语翻译:与协议有关的execution和performance有啥不同? 谢谢

markdown delayed_job的の実行·停止

Heroku上的rufus-scheduler和delayed_job:为啥要使用worker dyno?