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

我有一个新的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) => # 

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

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

我用script/delayed_job run启动一个worker

队列被清空:

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

但是,由于puts没有任何结果,记录logger调用不会logger任何内容,也不会引发exception。 我很感激任何帮助/见解或任何尝试。

默认情况下,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()方法构造。 更可靠。 还记得把你的作业定义作为一个单独的文件,这样类加载器可以在它运行时找到它(而不是只是在某个地方将类定义内联到你的模型中)。

Ben W绝对正确,请确保您有一个文件

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

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

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

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

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

我遇到了这个问题,我发现这是因为在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目录的自动加载的情况下解决这个问题。 有什么想法吗?

我刚把你的class级复制到irb并尝试做Me.new.perform

 Hello from me NameError: undefined local variable or method `logger' for # from (irb):6:in `perform' from (irb):14 

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

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

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

请记住,延迟的工作人员的’puts’命令将输出到它的标准输出,所以你可能永远不会看到这个。 如果你想进行任何日志记录,我认为你必须在你的perform方法中创建一个新的Logger实例才能这样做。

你在运行什么版本的delayed_job?

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

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

在终端,发布:

 tail -f log/development.log 

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

欢呼声