I'm trying to use Sidekiq to run the below job.
The job performs fine when not queued (perform_now) but fails when called as (perform_later), which uses Sidekiq.
AddEmployeesToRoomJob.perform_now room ## works fine
AddEmployeesToRoomJob.perform_later room ## breaks in Sidekiq
Error:
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 class AddEmployeesToRoomJob < ApplicationJob queue_as :default
def perform(room)
employees = Employee.all
if employees.length > 0
employees.each do |employee|
UserRoom.create(user: employee, room: room)
end
end
end
end
My Thoughts I don't understand why it can't find the room which I'm passing into the perform method. It's as though it somehow loses that variable in the queueifying / JSONifying of the job?
The Sidekiq docs say
"Unfortunately this means that if the [Room] record is deleted after the job is enqueued but before the perform method is called, exception handling is different."
They suggest a workaround but I don't see how that would help me:
rescue_from ActiveJob::DeserializationError do |exception|
# handle a deleted user record
end
Thanks in advance for any help!
If you build a web application you should minimize the amount of time spent responding to every user; a fast website means a happy user.
Sidekiq is an open-source framework that provides efficient background processing for Ruby applications. It uses Redis as an in-memory data structure to store all of its job and operational data. It's important to be aware that Sidekiq by default doesn't do scheduling, it only executes jobs.
Workarea applications use Sidekiq as a job queuing backend to perform units of work asynchronously in the background. These jobs, which include search indexing, cache busting, and cleanup of expired data, are defined as workers .
I don't think it is a good idea to pass the Room object into a Sidekiq worker. I've always passed the primary key for a database object and then re-queried. Try this.
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
Stumbled upon this myself and found the method discard_on
very useful. Mostly it is very unnecessary to do jobs on deleted or never created records.
Example:
class ApplicationJob < ActiveJob::Base
discard_on ActiveJob::DeserializationError do |job, error|
Rails.logger.error("Skipping job because of ActiveJob::DeserializationError (#{error.message})")
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With