2014-02-12 52 views
0

我使用Sidekiq在后台执行一些重处理。我在网上查找,但无法找到以下问题的答案。我使用:基本的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() 

两个问题:

  1. 如何让我的UserMailer sendmail的这个功能幂?换句话说,如果延迟方法运行两次,我如何确保它只发送一次邮件?会把它包装在这样的作品中吗?

    mail_sent =假 如果!mail_sent UserMailer.send_mail(上市) mail_sent =真 结束

我猜不是因为功能再次尝试,然后mail_sent被设置为false第二次贯穿。那么,我该如何做到这一点,以便UserMailer只运行一次。

  1. 在延迟的异步方法中调用的函数是否也是异步的?换句话说,是Class.call_example_function()异步执行的(未响应/请求周期的一部分吗?)如果不是这样,我应该用Class.delay.call_example_function()

总体而言,刚开始熟悉Sidekiq如此任何想法将不胜感激。

感谢

回答

0

关于幂等,你可以使用https://github.com/mhenrixon/sidekiq-unique-jobs宝石:

所有需要的是你专门为独特的设置sidekiq选项 像下面真:

sidekiq_options unique: true 

对于将来计划的工作,可以设置工作应该独一无二的时间。该作业对于配置的 秒的数量或作业完成之前将是唯一的。

*如果你想独特的工作坚持围绕它已成功处理后也只需要设置的unique_unlock_order,除了 东西:before_yield或:after_yield(unique_unlock_order = :从不)

我米不知道我明白问题的第二部分 - 当你方法调用delay整个方法调用被推迟到sidekiq进程。如果通过“响应/请求周期”,则表示您正在运行Web服务器,并从那里拨打delay,因此use_method内的所有呼叫都是从sidekiq进程调用的,因此在该循环之外。他们相对于彼此同步调用虽然...

4

我即将进入这一阶段,但一直在围绕循环,并有这个StackOverflow条目突出显示通过谷歌,它需要澄清。

幂等性问题和独特工作问题不是一回事。 '独特'宝石在即将被处理的地方查看作业的参数。如果他们发现有另一个工作具有在某个过期时间窗口内提交的相同参数,那么该工作实际上并未处理。

这些宝石的字面意思是他们所说的;他们会考虑在一定的时间范围内排队的工作是否独一无二。他们不会干预重试机制。在O.P.的问题中,如果Class.call_example_function()发生错误,电子邮件仍会发送两次,从而导致作业重试,但上一行代码已成功发送电子邮件。

除外:在撰写本文时,另一个答案中提到的宝石sidekiq-unique-jobs尚未更新为Sidekiq 3。另一种方法是sidekiq-middleware它做了很多相同的事情,但已被更新。

有到OP的电子邮件问题的无数种可能的解决方案和正确的东西,只有OP能的背景下评估他们的应用和执行环境。其中一个是:如果电子邮件只发送一次(“恭喜,你已经注册!”),那么封装在一个事务中的用户模型上的一个简单标志应该能够实现。假设一类User经由listing.user通过Listing关联访问,并且加入在一个布尔标志mail_sentUser模型(通过迁移),则:

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”代码引发异常,那么作业将失败并在稍后重试,但用户的“电子邮件发送”标志在第一次尝试中成功保存,因此电子邮件不会被重新发送。