在我的应用程序中,我尝试按顺序执行两个工作任务。 首先,使用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,它将引发一个异常,但我不知道如何做到这一点...(我也不确定重试将在使用异常方法处理之前等待多长时间,上面的解决方案我可以控制时间框架。)
答案 0 :(得分:2)
我相信"正确"并且大多数异步方法是拥有两个队列和两个工作人员:
当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