我正在使用Sidekiq在后台执行一些繁重的处理。我在网上看了但是找不到以下问题的答案。我正在使用:
Class.delay.use_method(listing_id)
然后,在课堂上,我有一个
self.use_method(listing_id)
listing = Listing.find_by_id listing_id
UserMailer.send_mail(listing)
Class.call_example_function()
两个问题:
如何使此功能成为UserMailer sendmail的幂等功能?换句话说,如果延迟方法运行两次,我如何确保它只发送一次邮件?将它包装在像这样的工作中吗?
mail_sent = false if!mail_sent UserMailer.send_mail(上市) mail_sent = true 端
我猜不会因为再次尝试该函数,然后在第二次运行时将mail_sent设置为false。那么我该怎么做才能让UserMailer只运行一次。
总的来说,只是熟悉Sidekiq所以任何想法都会受到赞赏。
由于
答案 0 :(得分:4)
我进入这个晚了,但是已经绕过这个循环,并且这个StackOverflow条目通过Google突出显示,它需要澄清。
幂等性问题和独特工作问题不是一回事。 “独特”宝石会在即将处理的作业点查看作业的参数。如果他们发现在某个到期时间窗口内有另一个具有相同参数的作业,则该作业实际上没有被处理。
宝石实际上就是他们所说的;他们考虑在某个时间窗口内排队的工作是否独特。它们不会干扰重试机制。对于OP的问题,如果Class.call_example_function()
引发错误从而导致作业重试,则电子邮件仍会被发送两次,但前一行代码已成功发送电子邮件。
旁白:在撰写本文时,Sidekiq 3尚未更新另一个答案中提到的sidekiq-unique-jobs
宝石。另一种选择是sidekiq-middleware
,它做了很多相同的事情,但已经更新。
O.P.的电子邮件问题有很多可能的解决方案,而正确的解决方案只有O.P.可以在其应用程序和执行环境的上下文中进行评估。一个是:如果电子邮件只发送一次(“恭喜,你已经注册!”)那么在事务中包含的用户模型上的一个简单标志应该可以解决问题。假设通过User
通过Listing
将listing.user
作为关联进行访问,并在mail_sent
模型中添加布尔标记User
(使用迁移),然后:
listing = Listing.find_by_id(listing_id)
unless listing.user.mail_sent?
User.transaction do
listing.user.mail_sent = true
listing.user.save!
UserMailer.send_mail(listing)
end
end
Class.call_example_function()
...因此,如果用户邮件程序抛出异常,则回滚事务并撤消对用户标志设置的更改。如果“call_example_function”代码抛出异常,则作业失败并稍后将重试,但是第一次尝试成功保存了用户的“发送电子邮件”标志,因此不会重新发送电子邮件。
答案 1 :(得分:0)
关于幂等性,您可以使用https://github.com/mhenrixon/sidekiq-unique-jobs gem:
只需要专门设置sidekiq选项即可 对于如下所示的唯一真实:
sidekiq_options unique: true
对于将来安排的工作,可以设置多长时间 工作应该是独一无二的。这个职位的数量是独一无二的 配置秒数或直到作业完成。
*如果您希望独特的作业即使在成功处理后仍然存在,那么只需将unique_unlock_order设置为 除了之前的任何东西:before_yield或:after_yield(unique_unlock_order = :从不)
我不确定我理解问题的第二部分 - 当你delay
方法调用时,整个方法调用被推迟到sidekiq进程。如果通过“响应/请求周期”表示您正在运行Web服务器,并且从那里调用delay
,那么use_method
中的所有调用都将从sidekiq进程调用,因此在外部调用那个周期。他们是相对于彼此同步调用,但是......