Delayed_job не выполняет метод execute, но очищает очередь заданий - PullRequest
17 голосов
/ 29 декабря 2010

У меня есть свежее приложение 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 ]

12 голосов
/ 25 января 2011

По умолчанию delayed_job уничтожает невыполненные задания:

Поэтому первым шагом является настройка инициализатора и деактивация этого поведения

Delayed::Worker.destroy_failed_jobs = false  

Кроме того, если вы получаете ошибку десериализации, томгновенный сбой задания.

Это вызывает удаление задания (если вы его еще не удалили).

Поэтому попробуйте добавить следующее в строку 120 worker.rb

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

Это довольно бесполезно, но, по крайней мере, тогда вы поймете, что это ошибка десериализации.

Я закончил тем, что просто использовал задание w.Метод выполнения ().Гораздо надежнее.Также не забудьте поместить определение задания в отдельный файл, чтобы загрузчик классов мог найти его во время работы (а не просто вставить определение класса в вашу модель).

6 голосов
/ 16 апреля 2011

Бен W абсолютно прав, убедитесь, что у вас есть файл под

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

Это определяет, как работник должен вести себя. В противном случае работник собирается просто удалить ошибки.

Как только вы это сделаете, вы сможете узнать больше о своей ошибке. Для моего примера я использовал delayed_job_mongoid, так что это добавило запись «last_error» (которую, я думаю, вы должны иметь в своей таблице mysql для delayed_job независимо от ..)

И как заключил Бен В., вам нужно убедиться, что создаваемый вами объект известен приложению (или работнику в этом отношении). Моя проблема заключалась в том, что я был в 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 было подтверждено, что это успешно. Я также протестировал создание и объект (пользовательский объект или любую другую модель) в этом методе execute, и он работал.

3 голосов
/ 13 ноября 2011

У меня была эта проблема, и я обнаружил, что это связано с тем, что в Rails 3 файлы в каталоге lib/ не загружаются автоматически. Для диагностики я добавил:

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

как упомянуто Беном В. Это сказало мне, что происходило, поскольку я мог осмотреть 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. Есть мысли?

0 голосов
/ 08 января 2011

проверьте журналы, вы должны увидеть что-то о сообщениях DelayedJob, по крайней мере, какое задание запущено и какое у него состояние выхода

в терминале, запустите:

tail -f log/development.log

, затем повторите попытку сконсоль rails для проверки того, что происходит, выполняя простой запрос ActiveRecord, затем используя DelayedJob.Вы можете прочитать, что зарегистрировано на другом терминале

ура, А.

0 голосов
/ 06 января 2011

Какую версию delayed_job вы используете?

Вам нужна ветка 2.1 в https://github.com/collectiveidea/delayed_job для Rails 3.0 и выше.

0 голосов
/ 01 января 2011

Я просто скопировал ваш класс в 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") }

Имейте в виду, что команда отложенного рабочего задания «кладет» выведет на свой стандартный вывод, так что вы, вероятно, никогда этого не увидите. И если вы хотите вести какую-либо запись, я думаю, что для этого вам нужно создать новый экземпляр Logger в вашем методе execute.

...