You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在rescue_from中重试ActionController的StaleObjectError处理动作?

解决ActiveRecord::StaleObjectError自动重试问题

控制器层面实现(推荐)

你直接用rescue_from ActiveRecord::StaleObjectError, :retry行不通,因为retry是Ruby关键字,并非可调用的方法。要实现全局自动重试,推荐用around_action包装所有动作的执行流程:

class ApplicationController < ActionController::API
  around_action :retry_on_stale_object_error

  private

  def retry_on_stale_object_error
    max_retries = 2 # 根据业务需求调整重试次数
    retry_count = 0

    begin
      yield # 执行当前控制器动作
    rescue ActiveRecord::StaleObjectError => e
      retry_count += 1
      retry if retry_count <= max_retries
      raise e # 超过重试次数后抛出原异常
    end
  end
end

所有继承自ApplicationController的控制器都会自动处理StaleObjectError,无需在每个动作里重复编写rescue块。

Rack层实现

如果想在更底层处理,也可以编写Rack中间件来重试整个请求:

# app/middlewares/stale_object_retry_middleware.rb
class StaleObjectRetryMiddleware
  def initialize(app)
    @app = app
    @max_retries = 2
  end

  def call(env)
    retry_count = 0
    begin
      @app.call(env)
    rescue ActiveRecord::StaleObjectError => e
      retry_count += 1
      retry if retry_count <= @max_retries
      raise e
    end
  end
end

然后在config/application.rb中注册中间件:

module YourAppName
  class Application < Rails::Application
    # 其他配置项...
    config.middleware.use StaleObjectRetryMiddleware
  end
end

注意:Rack层重试会重新走一遍完整请求流程(包括路由、其他中间件),开销比控制器层面更大,仅在需要覆盖所有请求场景时使用。

注意事项

  • 设置合理的重试次数,避免无限重试引发死循环
  • 确保更新操作是幂等的,重试不会产生意外副作用
  • 若特定动作无需重试,可通过skip_around_action :retry_on_stale_object_error, only: [:xxx]排除

内容的提问来源于stack exchange,提问作者Alan Savage

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 12:03:22