Action Job/Mailer 的 `deliver_now` 和 `deliver_later` 之间的区别

Posted

技术标签:

【中文标题】Action Job/Mailer 的 `deliver_now` 和 `deliver_later` 之间的区别【英文标题】:Difference between Action Job/Mailer's `deliver_now` and `deliver_later` 【发布时间】:2015-12-13 16:12:54 【问题描述】:

Rails 中与ActiveJob 交互的常见模式是使用perform() 方法设置一个作业,该方法通过perform_nowperform_later 异步调用

在Mailers的特殊情况下,您可以直接调用deliver_nowdeliver_later,因为ActiveJobActionMailer很好地集成。

rails documentation 有以下 cmets -

# If you want to send the email now use #deliver_now
UserMailer.welcome(@user).deliver_now
 
# If you want to send the email through Active Job use #deliver_later
UserMailer.welcome(@user).deliver_later

措辞使deliver_now 看起来不会使用ActiveJob 发送邮件。这是正确的,如果是这样,deliver_nowdeliver_later 之间的真正区别是什么?一个不是异步的吗?

同样,perform_nowperform_later 也有同样的区别吗?

谢谢!

【问题讨论】:

对我来说,ActionMailer 和 ActionJob 像这样相互混淆似乎很糟糕。 ActionJob 应该不知道工作正在做什么。 ActionMailer 应该能够被 ActionJob 延迟,而不必知道它正在被延迟,就像任何其他对象一样。对我来说,这似乎在 Rails 3、4 和 5 中被打破了。 【参考方案1】:

正如您在问题中所说,deliver_now 不使用ActiveJob

基本上,deliver_later 是异步的。当您使用此方法时,电子邮件不会在此刻发送,而是被推送到作业队列中。如果作业未运行,则不会发送电子邮件。 deliver_now 将在此时发送电子邮件,无论工作的状态如何。 Here 你可以查看deliver 方法的文档。

根据您的第二个问题,perform_now 将立即处理作业而不发送到队列。但是,perform_later 会将作业添加到队列中,并且一旦作业的队列空闲,就会执行作业。 Here 你可以查看perform 方法的文档。

【讨论】:

浏览器连接关闭了怎么办?还会执行 Deliver_later 吗? @gates deliver_later 在服务器端进行管理,因此浏览器连接是否关闭无关紧要。一旦作业被推送到队列中,它就会被发送(除非你终止作业进程)。 我想知道如果从脚本调用,通过'rails runner bin/send-lots-of-email.rb'执行,行为会发生什么变化?【参考方案2】:

除了 Daniel Batalla 所写的内容之外,我还做了一个观察:deliver_later 似乎执行惰性求值,而 deliver_now 没有。

我有一个 ActiveRecord 模型,它带有一个未存储在数据库中的附加属性 reset_token(来自 Michael Hartl 的 railstutorial.org;该模型将令牌的哈希版本存储在 reset_digest 列中)。

执行deliver_now 时,访问邮件视图中@modelreset_token 属性会按预期生成重置令牌。但是,在执行deliver_later 时,@model.reset_token 始终是nil。似乎deliver_later 使用数据库数据更新了模型,并且因为reset_token 是一个不受数据库支持的附加属性,所以此时它将是nil。 (代码文档嵌套太深,我无法在源代码中验证这一点。)

Michael 在教程中使用deliver_now。我不知道他这样做是为了避免懒惰的评估。但我花了一段时间才意识到我只需将 deliver_later 更改为 deliver_now 即可通过测试。

【讨论】:

由于deliver_later 是异步的,因此需要重新加载对象。就像任何异步作业一样。因为需要对工作进行新的更改(如果有)。 谢谢你,@bovender。我只是有同样的问题。在我的模型中,有几种方法可以计算总价/总价,如果我按如下方式运行邮件程序Mailer.payment_email(model, calculate_price).deliver_laterprice 始终是nil。使用deliver_now 会有所帮助,但它会破坏异步交付的所有好处。为了克服它,我用calculate_price.to_f 替换了calculate_price,它强制进行方法评估。在其他情况下,它可能是to_ito_s 等,具体取决于方法返回的数据类型。

以上是关于Action Job/Mailer 的 `deliver_now` 和 `deliver_later` 之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

less封装样式有规律的类选择器-遁地龙卷风

京东好货

传输矩阵发生器

mysql自定函数

MySQL函数--

31.分隔符异常分析