Passing an options hash to a sidekiq worker

Blankman picture Blankman · Sep 25, 2016 · Viewed 8.4k times · Source

I remember when I tried passing a params (JSON) option to a sidekiq worker method and it didn't work out well because I was referencing the option like:

options[:email_address]

But I think it would have worked if I did:

options["email_address"]

So for some reason when it gets serialized and deserialized the hash can only be referenced with a string not a symbol.

Is this a safe practise?

I have a transaction email worker that looks like:

class TransactionEmailWorker
    include Sidekiq::Worker

  def perform(action, options)
    case action
    when 'welcome'
      welcome(options["email_address"], options["something_else"])
    when 'reset_password'
      reset_password(options["email_address"])
    end
  end

  def welcome(email, title)
    # ...
  end

  def reset_password(email)
   # ..
  end

Answer

dlachasse picture dlachasse · Sep 25, 2016

This is what the Sidekiq wiki page states:

The arguments you pass to perform_async must be composed of simple JSON datatypes: string, integer, float, boolean, null, array and hash. The Sidekiq client API uses JSON.dump to send the data to Redis. The Sidekiq server pulls that JSON data from Redis and uses JSON.load to convert the data back into Ruby types to pass to your perform method. Don't pass symbols, named parameters or complex Ruby objects (like Date or Time!) as those will not survive the dump/load round trip correctly.

Passing a Ruby hash is valid as it is able to serialize into valid JSON. So to answer your question, it's safe practice.

serialized_args = JSON.dump({email_address: "[email protected]", something_else: "thing"})
=> "{\"email_address\":\"[email protected]\",\"something_else\":\"thing\"}"

JSON.load(serialized_args)
=> {"email_address"=>"[email protected]", "something_else"=>"thing"}