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?
Heroku 上的 Delayed_Job 显示“禁止”错误