2016-08-20 4 views
2

Я пытаюсь использовать Sidekiq для запуска ниже заданного задания.Использование Sidekiq для активного задания и получение ActiveJob :: DeserializationError

Работа выполняется нормально, если не поставлена ​​в очередь (выполняется_и_на), но сбой при вызове (perform_later), который использует Sidekiq.

AddEmployeesToRoomJob.perform_now room ## works fine 
AddEmployeesToRoomJob.perform_later room ## breaks in Sidekiq 

Ошибка:

AddEmployeesToRoomJob JID-da24b13f405b1ece1212bbd5 INFO: fail: 0.003  sec 
2016-08-20T14:57:16.645Z 19456 TID-owmym5fbk WARN:  {"class":"ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper","wrapped" :"AddEmployeesToRoomJob","queue":"default","args": [{"job_class":"AddEmployeesToRoomJob","job_id":"0ba5bd30-e281-49a7-a93f- 6e50445183ac","queue_name":"default","priority":null,"arguments": [{"_aj_globalid":"gid://dragonfly/Room/1"}],"locale":"en"}],"retry":true, "jid":"da24b13f405b1ece1212bbd5","created_at":1471704675.739077,"enqueued _at":1471705036.6406531,"error_message":"Error while trying to  deserialize arguments: Couldn't find Room with  'id'=1","error_class":"ActiveJob::DeserializationError","failed_at":14717 04675.946183,"retry_count":4,"retried_at":1471705036.644416} 
2016-08-20T14:57:16.645Z 19456 TID-owmym5fbk WARN:  ActiveJob::DeserializationError: Error while trying to deserialize  arguments: Couldn't find Room with 'id'=1 
2016-08-20T14:57:16.645Z 19456 TID-owmym5fbk WARN:  /Users/tamlyn/.rvm/gems/ruby-2.2.3/gems/activerecord- 5.0.0.1/lib/active_record/relation/finder_methods.rb:357:in  `raise_record_not_found_exception!' 

My Job класс AddEmployeesToRoomJob < ApplicationJob queue_as: По умолчанию

def perform(room) 
    employees = Employee.all 
    if employees.length > 0 
     employees.each do |employee| 
     UserRoom.create(user: employee, room: room) 
     end 
    end 
    end 
end 

Мои Мысли Я не понимаю, почему он не может найти комнату, в которую я перехожу в метод выполнения. Как будто это как-то теряет эту переменную в очереди/JSONifying задания?

Sidekiq документы говорят

«К сожалению, это означает, что если [номер] запись будет удалена после того, как работа будет помещён, но до того, как метод выполнения называется, обработка исключений отличается.»

Они предлагают обходной путь, но я не понимаю, как это помогло бы мне:

rescue_from ActiveJob::DeserializationError do |exception| 
    # handle a deleted user record 
end 

Заранее спасибо за любую помощь!

+1

https://github.com/mperham/sidekiq/wiki/Проблемы и устранение неполадок # не могу найти-modelname-with-id12345 –

ответ

5

Я не думаю, что это хорошая идея передать объект Room в работника Sidekiq. Я всегда передавал первичный ключ для объекта базы данных, а затем повторно запрашивал. Попробуй это.

AddEmployeesToRoomJob.perform_later room.id 

def perform(room_id) 
    room = Room.find(room_id) 
    employees = Employee.all 
    if employees.length > 0 
     employees.each do |employee| 
     UserRoom.create(user: employee, room: room) 
     end 
    end 
    end 
end 
+0

Спасибо! Это прекрасно работает ... –

+0

@TamlynR, если этот ответ решает вашу проблему, не могли бы вы сделать это как ответ. Если нет, сообщите мне, что еще нужно. – kcdragon

0

Не рекомендуется отправлять объект Ruby в качестве параметра для работника-помощника. Вы можете отправить Id как параметр и инициализировать объект внутри метода выполнения. Если вы хотите отправить объект, вы можете сбросить объект Ruby в любой другой формат, например Json/Binary/yml, следующим образом.

object.to_json 

Или

Marshal.dump(object) 

И перед использованием объектов внутри выполнения метода вы можете де-сериализации объекта на объект Ruby, следующим образом.

JSON.parse(serialized_object) 

Или

Marshal.load(serialized_object) 

Это решение для вашей проблемы, но не идеальное решение.

+1

Спасибо, это действительно интересно –

1

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

Вы можете найти более подробную информацию здесь: https://github.com/mperham/sidekiq/wiki/FAQ#why-am-i-seeing-a-lot-of-cant-find-modelname-with-id12345-errors-with-sidekiq

В нашем проекте мы закодировали модель беспокойство, чтобы иметь возможность добавлять динамический после фиксации блоков кода.

module AfterCommitOnce 
    extend ActiveSupport::Concern 

    included do 
    after_commit :execute_after_commit_handlers 
    end 

    def after_commit_once(&block) 
    @after_commits = @after_commits || [] 
    @after_commits << block 
    end 

    private 

    def execute_after_commit_handlers 
    @after_commits = @after_commits || [] 
    @after_commits.each do |ac| 
     ac.call 
    end 
    @after_commits = [] 
    end 
end 

Добавление этой проблемы вам Employee модель вы можете указать, какую работу вы хотите выполнить после фиксации всех изменений в базу данных с вами:

... 
employee.after_commit_once do 
    AddEmployeesToRoomJob.perform_later 
end 
employee.save! 
Смежные вопросы