Как Sidekiq передает аргументы методу выполнения?

У меня есть работник Sidekiq:

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

Я передать хэш perform_async метод, но я думаю, что параметры Все передаваемые на perform метода не одного и того же типа, что и те, переданных perform_async. Я попытался использовать logger.info и p для отладки моей проблемы, но ничего не выводилось...

Проблема в том, что задание добавляется в очередь электронной почты, но никогда не обрабатывается. Я даже попытался создать исключение в методе perform (в первой строке метода), но ничего не выводилось...

Я знаю, что работает следующий работник:

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

Таким образом, проблема заключается в хэш-параметре (опции). Что я делаю неправильно?

Ответ 1

Из документации Sidekiq:

Аргументы, которые вы передаете perform_async, должны состоять из простых типов данных JSON: string, integer, float, boolean, null, array и hash. Клиентский API Sidekiq использует JSON.dump для отправки данных в Redis. Сервер Sidekiq извлекает данные JSON из Redis и использует JSON.load для преобразования данных обратно в типы Ruby для перехода к вашему методу выполнения. Не пропускайте символы или сложные объекты Ruby (например, Date или Time!), Так как они не смогут нормально выжить в полете.

Это можно увидеть на консоли:

> 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

Похоже, вы используете символы в качестве ключей для хэш- options. Если вы переключитесь на строковые ключи, он должен работать.

Ответ 2

Вы используете очередь, называемую электронной почтой, поэтому вам нужно будет запустить sidekiq -q email.