Подтвердить что ты не робот

Delayed_job не выполняет метод выполнения, но освобождает очередь заданий

У меня есть новое приложение для рельсов 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, и исключение не возникает. Я был бы признателен за любую помощь/понимание или что-нибудь, что можно попробовать.

4b9b3361

Ответ 1

По умолчанию delayed_job уничтожает сбойные задания:

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

Delayed::Worker.destroy_failed_jobs = false  

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

Это приводит к удалению задания (если вы его не удалили).

Итак, попробуйте добавить следующее вокруг строки 120 рабочего .rb

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

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

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

Ответ 2

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

Ответ 3

У меня была эта проблема, и я обнаружил, что это связано с тем, что в 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. Любые мысли?

Ответ 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

Доступен ли ваш класс к "logger"?

Вы можете попробовать сделать что-то еще, например, открыть и записать в файл?

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

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

Ответ 6

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

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

tail -f log/development.log

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

веселит, А.