代码之家  ›  专栏  ›  技术社区  ›  Maxence

从工作区内重试Sidekiq工作区

  •  0
  • Maxence  · 技术社区  · 6 年前

    在我的应用程序中,我尝试按顺序执行两个工作任务。 首先,使用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 这将引发一个例外,但我不确定如何做到这一点…(另外,我不确定在用exception方法处理之前重试会等待多长时间,通过上面的解决方案,我可以控制时间范围…)

    2 回复  |  直到 6 年前
        1
  •  2
  •   ragav ramachandran    6 年前

    如果不希望有嵌套的工作人员,则在 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
    
        2
  •  2
  •   ekampp    6 年前

    我认为实现这一点的“正确”和最异步的方法是拥有两个队列和两个工人:

    • 队列1:CreatePdfWorker
    • 队列2:sendpfWorker

    当CreatePdfWorker生成PDF后,它会将sendPdfWorker与新生成的PDF和收件人排队。

    通过这种方式,每个工作人员都可以独立工作并异步地从队列中提取数据,而您不必为Sidekiq的设计选择而苦苦挣扎。