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

时间:2010-12-29 07:32:14

标签: ruby-on-rails ruby-on-rails-3 delayed-job

我有一个全新的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调用中没有记录任何内容,也没有引发异常。我很感激任何帮助/见解或任何尝试。

6 个答案:

答案 0 :(得分:12)

默认情况下,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)

这是相当无益的,但至少你会知道这是一个反序列化错误。

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

答案 1 :(得分:6)

Ben W绝对正确,请确保您有

下的文件
"#{Rails.root}/config/initializers/delayed_job_worker.rb"

这定义了工人应该如何表现。工人将悄悄地删除错误。

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

正如Ben W总结的那样,你需要确保你正在创建的对象是应用程序(或者工作人员)所知道的。我的问题是我在Rails Console中测试了一个类对象。工人不知道这个班级,所以它被禁止了。

在我的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文件中确认这是成功的。我还在这个执行方法中测试了创建和对象(用户对象或你可能拥有的任何模型),并且它有效。

答案 2 :(得分:3)

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

# 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目录的自动加载的情况下解决这个问题。有什么想法吗?

答案 3 :(得分:0)

我刚刚将您的课程复制到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实例才能这样做。

答案 4 :(得分:0)

你在运行什么版本的delayed_job?

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

答案 5 :(得分:0)

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

在终端中,启动:

tail -f log/development.log

然后从rails控制台重试以检查执行简单的ActiveRecord查询会发生什么,然后使用DelayedJob。你可以阅读在另一个终端上记录的内容

欢呼声, 甲