Passing objects to a Sidekiq worker will not always work, and you should instead pass simple references to those objects.
Here is an example of what will not work:
class CalculateProgressWorker include Sidekiq::Worker def perform(user_id, date) Progress.calculate_for(user_id: user_id, date: date) end end
The contrived example is a worker that calculates something (progress) based on information about user and date.
Progress.calculate_for expects user_id, and a
Date object. Therefore, you might be inclined to do this when calling this worker:
today = Time.zone.today CalculateProgressWorker.perform_async(user_id, today)
However, you will run into a type error if you pass in a
Date object to the Sidekiq Worker.
Problem is that Sidekiq translates all your arguments into JSON format before storing them in the Redis queue.
CalculateProgressWorker will then pull from the Redis queue and try to perform the task.
JSON.load to store and pull data from Redis.
For example, you
today object will be transformed as follows:
today = Time.zone.today => Sat, 23 May 2015 today.class => Date # Sidekiq stores the data to Redis today_in_redis = JSON.dump(today) => "\"2015-05-23\"" today_in_redis.class => String # Sidekiq retrieves the data from Redis retrieved_today = JSON.load(today_in_redis) => "2015-05-23" retrieved_today.class => String
When the job is finally executed, your argument will have turned into a different type, thus causing unexpected behavior.
It is the best practice to keep your job parameters simple. Avoid passing complicated objects to Sidekiq workers.
In our example, we could explicitly pass
String object to
CalculateProgressWorker instead of
Date object, and use
Date.parse to parse the
String back to
class CalculateProgressWorker include Sidekiq::Worker def perform(user_id, date_string) Progress.calculate_for(user_id: user_id, date: Date.parse(date_string)) end end
today = Time.zone.today CalculateProgressWorker.perform_async(user_id, today.to_s)
today is not entirely necessary because Sidekiq will transform
String object as we saw before. However, it is a good idea to make it obvious to other readers that you are passing in
String, not a