Del*_*ang 0 ruby multithreading idempotent sidekiq
我正在使用 Sidekiq 在后台执行一些繁重的处理。我在网上查了一下,但找不到以下问题的答案。我在用:
Class.delay.use_method(listing_id)
Run Code Online (Sandbox Code Playgroud)
然后,在课堂上,我有一个
self.use_method(listing_id)
listing = Listing.find_by_id listing_id
UserMailer.send_mail(listing)
Class.call_example_function()
Run Code Online (Sandbox Code Playgroud)
两个问题:
如何使这个函数对 UserMailer sendmail 是幂等的?换句话说,如果延迟方法运行两次,我如何确保它只发送一次邮件?会把它包装成这样的工作吗?
mail_sent = false if !mail_sent UserMailer.send_mail(listing) mail_sent = true end
我猜不是,因为再次尝试该函数,然后第二次运行时将 mail_sent 设置为 false。那么如何才能让 UserMailer 只运行一次。
总的来说,只是熟悉 Sidekiq,所以任何想法都将不胜感激。
谢谢
我来晚了,但一直在循环中并且通过谷歌显眼地出现了这个 StackOverflow 条目,它需要澄清。
幂等性问题和独特工作的问题不是一回事。'unique' gems 在它即将被处理时查看作业的参数。如果他们发现在某个到期时间窗口内提交了具有相同参数的另一个作业,则该作业实际上并未被处理。
宝石实际上就是他们所说的那样;他们考虑在某个时间窗口内排队的作业是否是唯一的。它们不会干扰重试机制。在 OP 问题的情况下,如果Class.call_example_function()抛出错误从而导致作业重试,电子邮件仍会被发送两次,但前一行代码已成功发送电子邮件。
旁白:将sidekiq-unique-jobs在另一个答复中提到创业板尚未在写作时更新的Sidekiq 3。另一种方法是sidekiq-middleware做同样的事情,但已经更新。
OP 的电子邮件问题有多种可能的解决方案,正确的解决方案只有 OP 才能在其应用程序和执行环境的上下文中进行评估。一种是:如果电子邮件只发送一次(“恭喜,您已经注册!”),那么封装在事务中的 User 模型上的一个简单标志应该可以解决问题。假设一类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()
Run Code Online (Sandbox Code Playgroud)
...这样,如果用户邮件程序抛出异常,则事务将回滚并撤消对用户标志设置的更改。如果“call_example_function”代码抛出异常,则作业将失败并稍后重试,但用户的“电子邮件已发送”标志在第一次尝试时已成功保存,因此不会重新发送电子邮件。