【问题标题】:deliver_later with Sidekiq causes 500 error when unable to connect to Redis无法连接到 Redis 时,使用 Sidekiq 的 Deliver_later 会导致 500 错误
【发布时间】:2016-11-01 19:23:34
【问题描述】:

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

def create
  @user = User.create(user_params)

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

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

很遗憾,如果 deliver_later 无法连接到 Redis,则整个 create 请求将失败并返回 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 的子类。

【问题讨论】:

  • 为什么不简单地挽救异常?
  • @user3033467 在哪里?我在整个应用程序中都有 Deliver_later 代码,所以想从一个地方完成。
  • 我不知道有任何方法可以在不使用猴子补丁或引入外观的情况下全局捕获该错误。

标签: ruby-on-rails actionmailer sidekiq


【解决方案1】:

为了防止在 Redis 关闭时对 deliver_later 的调用崩溃,我们添加了以下猴子补丁:

# 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)

【讨论】:

  • 你把这个放在什么文件里?这是什么版本的rails?遇到完全相同的问题,想知道我是否仍然可以将它用于我当前的 Rails 5.2 项目,或者你们是否最终都重构了它。
  • @Zachary 这本来是用于 Rails 4.2.x 的(我在跳到 5 之前就离开了)。我们将所有这些猴子补丁保存在 config/initializers/ 中,所以这可能是 config/initializers/message_delivery_with_silent_queueing_errors.rb 不知道它在 5.x 中是否仍然有效,但值得一试!
猜你喜欢
  • 2013-01-28
  • 1970-01-01
  • 2019-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-31
  • 1970-01-01
  • 2015-02-06
相关资源
最近更新 更多