Rails 6、如何保证一个Mailer不会重试,例如隐式(非显式)使用Active job时,如何添加ActiveJob retry: false设置?
In Rails 6, how ensure a Mailer will not retry, eg, how add ActiveJob retry: false setting when Active job is used implicitly (not explicitly)?
在新的 Rails 6.1 应用程序中,我想明确禁用邮件作业的任何重试。
由于 ActionMailer 自动 使用 ActiveJob,我如何为特定邮件程序添加自定义 ActiveJob 配置 class,例如禁用 sidekiq 重试?
如果使用了 显式 ActiveJob class,很简单:
class ExampleJob < ActiveJob::Base
sidekiq_options retry: false # custom setting allowed here in a JOB
def perform(*args)
# Perform Job
end
end
但是在像 ActionMailer 这样使用 ActiveJob 的情况下隐式(“幕后”)如何明确禁用 sidekiq 重试邮件作业?
例如,发送这样的电子邮件时:
AccountInvitationsMailer.with(account_invitation: self).invite.deliver_later
当当前邮件代码为:
class ApplicationMailer < ActionMailer::Base
default from: "someone@example.com"
layout "mailer"
# Include any view helpers from your main app to use in mailers here
helper ApplicationHelper
end
class AccountInvitationsMailer < ApplicationMailer
def invite
@account_invitation = params[:account_invitation]
@account = @account_invitation.account
@invited_by = @account_invitation.invited_by
name = @account_invitation.name
email = @account_invitation.email
mail(
to: "#{name} <#{email}>",
from: "#{@invited_by.name} <invites@example.com>",
subject: t(".subject", inviter: @invited_by.name, account: @account.name)
)
end
end
实际上,您可以明确设置要在 ActionMailer 上使用的 ActiveJob class,例如:
class ApplicationMailer < ActionMailer::Base
self.delivery_job = ExampleJob
# blah blah blah
end
因此您稍后可以在 ActiveJob class 中设置任何其他内容。
如果有人看到 Rails 版本 >= 6(也在 7 中测试过),这里有一个更详细的 ExampleJob
实现。
考虑上面的例子和这样的调用:
AccountInvitationsMailer.with(some: 'params').invite.deliver_later
ExampleJob
class 应该类似于:
class ExampleJob < ApplicationJob
# rescue_from StandardError, with: :notify_to_exception_tracker
# Any other customization option
# Perform will receive 4 params
# mailer: The original mailer class, i.e. `AccountInvitationsMailer`
# mailer_method: The method called in the mailer, i.e. `invite`
# delivery_method: The delivery method used, i.e. `deliver_later`
# args: Original arguments sent to the mailer wrapped in params container, i.e. `{ params: { some: 'params' } }`
def perform(mailer, mail_method, delivery_method, args)
klass = mailer.constantize
klass.with(args[:params]).public_send(mail_method).send(delivery_method)
end
# ...
end
最后,原始问题的另一种替代方法是通过在相关环境文件(开发、暂存、生产等)中设置 config.action_mailer.raise_delivery_errors = false
来忽略交付错误
在新的 Rails 6.1 应用程序中,我想明确禁用邮件作业的任何重试。
由于 ActionMailer 自动 使用 ActiveJob,我如何为特定邮件程序添加自定义 ActiveJob 配置 class,例如禁用 sidekiq 重试?
如果使用了 显式 ActiveJob class,很简单:
class ExampleJob < ActiveJob::Base
sidekiq_options retry: false # custom setting allowed here in a JOB
def perform(*args)
# Perform Job
end
end
但是在像 ActionMailer 这样使用 ActiveJob 的情况下隐式(“幕后”)如何明确禁用 sidekiq 重试邮件作业?
例如,发送这样的电子邮件时:
AccountInvitationsMailer.with(account_invitation: self).invite.deliver_later
当当前邮件代码为:
class ApplicationMailer < ActionMailer::Base
default from: "someone@example.com"
layout "mailer"
# Include any view helpers from your main app to use in mailers here
helper ApplicationHelper
end
class AccountInvitationsMailer < ApplicationMailer
def invite
@account_invitation = params[:account_invitation]
@account = @account_invitation.account
@invited_by = @account_invitation.invited_by
name = @account_invitation.name
email = @account_invitation.email
mail(
to: "#{name} <#{email}>",
from: "#{@invited_by.name} <invites@example.com>",
subject: t(".subject", inviter: @invited_by.name, account: @account.name)
)
end
end
实际上,您可以明确设置要在 ActionMailer 上使用的 ActiveJob class,例如:
class ApplicationMailer < ActionMailer::Base
self.delivery_job = ExampleJob
# blah blah blah
end
因此您稍后可以在 ActiveJob class 中设置任何其他内容。
如果有人看到 Rails 版本 >= 6(也在 7 中测试过),这里有一个更详细的 ExampleJob
实现。
考虑上面的例子和这样的调用:
AccountInvitationsMailer.with(some: 'params').invite.deliver_later
ExampleJob
class 应该类似于:
class ExampleJob < ApplicationJob
# rescue_from StandardError, with: :notify_to_exception_tracker
# Any other customization option
# Perform will receive 4 params
# mailer: The original mailer class, i.e. `AccountInvitationsMailer`
# mailer_method: The method called in the mailer, i.e. `invite`
# delivery_method: The delivery method used, i.e. `deliver_later`
# args: Original arguments sent to the mailer wrapped in params container, i.e. `{ params: { some: 'params' } }`
def perform(mailer, mail_method, delivery_method, args)
klass = mailer.constantize
klass.with(args[:params]).public_send(mail_method).send(delivery_method)
end
# ...
end
最后,原始问题的另一种替代方法是通过在相关环境文件(开发、暂存、生产等)中设置 config.action_mailer.raise_delivery_errors = false
来忽略交付错误