当无法连接到Redis时,带有Sidekiq的deliver_later会导致500错误

时间:2016-08-03 17:04:32

标签: ruby-on-rails actionmailer sidekiq

在我的一个Rails应用程序控制器中,我做了类似这样的事情:

def create
  @user = User.create(user_params)

  # send welcome email
  UserMailer.welcome(@user).deliver_later
end

现在,我故意禁用我的Redis服务器,以便我可以复制在我的应用无法建立连接的情况下会发生的情况。

不幸的是,如果create无法连接到Redis,则整个deliver_later请求失败并显示500。

我想要的是请求仍然成功,但是邮件程序无声地失败。

我该如何做到这一点?

其他信息:

在config / initializers / action_mailer.rb中:

  rescue_from(Redis::CannotConnectError) do |exception|
      Rails.logger.error "Original record not found: #{@serialized_arguments.join(', ')}"
  end

在异常时永远不会被调用。我尝试了rescue_from(StandardError)(Exception),但从未调用过。

我使用sidekiq作为我的作业队列适配器:

config.active_job.queue_adapter = :sidekiq

我得到的500错误是:

Redis::CannotConnectError (Error connecting to Redis on localhost:6379 (Errno::ECONNREFUSED)):

我的UserMailerApplicationMailer的子类,是ActionMailer::Base的子类。

1 个答案:

答案 0 :(得分:0)

为了防止在Redis关闭时调用deliver_later崩溃,我们添加了以下monkey-patch:

# If +raise_delivery_errors+ is false, errors occurring while attempting to
# enqueue the email for delivery will be ignored (for instance, if Redis is
# unreachable). In these cases, the email will never be delivered.
module MessageDeliveryWithSilentQueueingErrors
  def deliver_later
    super
  rescue Redis::CannotConnectError => e
    raise if raise_delivery_errors
    # Log details of the failed email here
  end

  def deliver_later!
    super
  rescue Redis::CannotConnectError => e
    raise if raise_delivery_errors
    # Log details of the failed email here
  end
end

ActionMailer::MessageDelivery.send(:prepend, MessageDeliveryWithSilentQueueingErrors)