我有一个全新的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
调用中没有记录任何内容,也没有引发异常。我很感激任何帮助/见解或任何尝试。
答案 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。你可以阅读在另一个终端上记录的内容
欢呼声, 甲