18

I have this Sidekiq worker:

class DealNoteWorker
  include Sidekiq::Worker
  sidekiq_options queue: :email

  def perform(options = {})
    if options[:type] == "deal_watch_mailer"
      deal_watchers = DealWatcher.where("deal_id = ?", options[:deal_id])

      deal_note = DealNote.find(options[:deal_note_id])

      current_user = User.find(options[:current_user_id])

      deal_watchers.each do |deal_watcher|
        unless deal_watcher.user_id == options[:current_user_id]
          # Tell the DealWatchMailer to send emails to ALL watchers advising of change to deal
          if deal_watcher.user.active
            DealWatchMailer.deal_watch_email(deal_watcher, nil, deal_note, current_user, options[:url]).deliver
          end
        end
      end
    elsif options[:type] == "deal_note_mailer"
      options[:user_ids].each do |id|
        if DealWatcher.where("deal_id = ? and user_id =?", options[:deal_id], id).count == 0
          deal_note = Deal.find(options[:deal_note_id])
          user = User.find_by_id(id)
          DealNoteMailer.deal_note_email(deal_note, user, options[:url]).deliver
        end
      end
    end
  end
end

I pass a hash to the perform_async method, but I think that the parameters transfered to the perform method are not of the same type as the ones passed to perform_async. I tried to user logger.info and p to debug my issue but nothing gets outputted...

The issue is that the job is added to the email queue but never gets processed. I even tried to raise an exception in the perform method (on the first line of the method) but nothing was outputted either...

I know as a fact that the following worker works:

class DealNoteWorker
  include Sidekiq::Worker

  def perform(deal_id, deal_note_id, current_user_id, url)
    deal_watchers = DealWatcher.where("deal_id = ?", deal_id)

    deal_note = DealNote.find(deal_note_id)

    current_user = User.find(current_user_id)

    deal_watchers.each do |deal_watcher|
      unless deal_watcher.user_id == current_user_id
        # Tell the DealWatchMailer to send emails to ALL watchers advising of change to deal
        if deal_watcher.user.active
          DealWatchMailer.deal_watch_email(deal_watcher, nil, deal_note, current_user, url).deliver
        end
      end
    end
  end
end

So the problem lies in the hash parameter (options). What am I doing wrong please?

Peter Butterworth
  • 181
  • 1
  • 1
  • 3
  • You sure that you've started the sidekiq workers? Run `bundle exec sidekiq` in another terminal. Also, you're using a queue called `email`, so you'll need to run `sidekiq -q email`. – Aaron Breckenridge Apr 04 '13 at 00:25
  • yeah, that was the problem. I needed to start sidekiq with the email queue. So I added a list of queues in a sidekiq.yml config file and that fixed the problem. Could you add your comment as answer so that I can accept it? – Peter Butterworth Apr 04 '13 at 07:39

3 Answers3

32

From the Sidekiq documentation:

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 or complex Ruby objects (like Date or Time!) as those will not survive the dump/load round trip correctly.

You can see this on the console:

> options = { :a => 'b' }
> how_sidekiq_stores_the_options = JSON.dump(options)
> how_sidekiq_loads_the_options = JSON.load(how_sidekiq_stores_the_options)
> how_sidekiq_stores_the_options == how_sidekiq_loads_the_options
  false

It looks like you are using symbols as the keys for your options hash. If you switch to string keys, it should work.

mertonium
  • 321
  • 3
  • 3
  • Also note that Hashes can be problematic. Passing these as JSON solved a mysterious "wrong number of arguments" error for me. – ericpeters0n Apr 11 '14 at 19:05
  • I've got something similar. The first time the worker runs I get an exception that my code raises, the next retry I get the wrong number of argument error. – OpenCoderX Jul 16 '14 at 12:13
2

You're using a queue called email, so you'll need to run sidekiq -q email.

Arc676
  • 4,445
  • 3
  • 28
  • 44
Henley
  • 21,258
  • 32
  • 119
  • 207
0

Beware that hash keys sent as symbols will be converted to strings in the transfer to Sidekiq perform.

Martin Streicher
  • 1,983
  • 1
  • 18
  • 18