如何在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
相关产品推荐
相关产品推荐

