Retry Sidekiq рабочий изнутри рабочий - PullRequest
0 голосов
/ 26 мая 2018

В моем приложении я пытаюсь последовательно выполнить две рабочие задачи.Сначала создается PDF-файл с помощью Wicked pdf, а затем, после создания PDF-файла, отправляется электронное письмо двум разным получателям с прикрепленным PDF-файлом.

Это то, что называется в контроллере:

PdfWorker.perform_async(@d.id)
MailingWorker.perform_in(1.minutes, @d.id,@d.class.name.to_s)

Первый сотрудник создает PDF, а второй сотрудник отправляет электронную почту.

Вот второй работник:

class MailingWorker
  include Sidekiq::Worker
  sidekiq_options retry: false    
  def perform(d_id,model)

    @d = eval(model).find(d_id)
    @model = model
    if @d.pdf.present?
      ProfessionnelMailer.notification_d(@d).deliver
      ClientMailer.notification_d(@d).deliver
    else
      MailingWorker.perform_in(1.minutes, @d.id, @model.to_s)
    end
  end
end

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

Хотя, если PDF-файл определенно не был обработан, вышеприведенное заканчивается бесконечным циклом.

Есть ли способ исправить это?

Один из вариантов, который я вижу, - это вызвать второго работника внутри работника создания PDF, хотя я не очень хочу вкладывать работников слишком глубоко.Это делает мой контроллер более понятным, чтобы они были разделены, я вижу последовательность действий.Но любые советы приветствуются.

Другой вариант заключается в использовании sidekiq_options retry: 5 и запросе повторной попытки контроллера, которая может быть посчитана до полной 5 попыток, вместо повторной попытки работника с else MailingWorker.perform_in(1.minutes, @d.id, @model.to_s), но я нене знаю, как это сделать.В соответствии с этим потоком https://github.com/mperham/sidekiq/issues/769 было бы вызвать исключение, но я не уверен, как это сделать ... (также я не уверен, сколько еще будет ждать повторная попытка перед обработкой методом исключения, срешение выше, я могу контролировать сроки ..)

Ответы [ 2 ]

0 голосов
/ 27 мая 2018

Если вы не хотите иметь вложенных рабочих, то в MailingWorker вместо того, чтобы ставить его в очередь, выведите исключение, если PDF-файл отсутствует.Кроме того, настройте параметр «Повторить рабочий», чтобы sidekiq поместил его в очередь повторных попыток и через некоторое время снова запустил.Согласно документации,

Sidekiq will retry failures with an exponential backoff using the 
formula (retry_count ** 4) + 15 + (rand(30) * (retry_count + 1)) (i.e. 
15, 16, 31, 96, 271, ... seconds + a random amount of time). It will 
perform 25 retries over approximately 21 days.

Рабочий код будет больше похож на

class MailingWorker
  include Sidekiq::Worker
  sidekiq_options retry: 5

  def perform(d_id,model)

    @d = eval(model).find(d_id)
    @model = model
    if @d.pdf.present?
      ProfessionnelMailer.notification_d(@d).deliver
      ClientMailer.notification_d(@d).deliver
    else
      raise "PDF not present"
    end
  end
end
0 голосов
/ 27 мая 2018

Я считаю, что «правильный» и наиболее асинхронный способ сделать это состоит в том, чтобы иметь две очереди и двух рабочих:

  • Очередь 1: CreatePdfWorker
  • Очередь 2: SendPdfWorker

Когда CreatePdfWorker сгенерировал PDF, он ставит в очередь SendPdfWorker с недавно созданным PDF и получателями.

Таким образом, каждый работник может работать независимо и асинхронно вырывать из очереди, и вы не боретесь с выбором дизайна Sidekiq.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...