从工人内部重试Sidekiq工作人员

时间:2018-05-26 11:15:07

标签: ruby-on-rails ruby-on-rails-5 sidekiq

在我的应用程序中,我尝试按顺序执行两个工作任务。 首先,使用Wicked pdf创建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 :(得分:2)

我相信"正确"并且大多数异步方法是拥有两个队列和两个工作人员:

  • 队列1:CreatePdfWorker
  • 队列2:SendPdfWorker

当CreatePdfWorker生成PDF时,它会将SendPdfWorker与新生成的PDF和收件人一起排队。

通过这种方式,每个工作人员可以独立工作并且异常地从队列中拔出,并且您不会反对Sidekiq的设计选择。

答案 1 :(得分:2)

如果您不想拥有嵌套工作者,那么在MailingWorker而不是再次将其排队,如果PDF不存在则引发异常。 此外,配置worker retry选项,以便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