如何针对单个请求修改Faraday中间件配置?
针对特定Faraday请求实现自定义重试逻辑
问题描述
已配置好全局Faraday客户端,默认针对网络错误、5xx状态码进行3次重试:
client = Faraday.new(url: base_url) do |f| f.request :retry, { max: 3, backoff_factor: 2 } f.request :authorization, 'Bearer', -> { access_token } f.request :json f.response :json f.response :raise_error end
现在需要针对特定请求/wait-for-data,在响应成功但env.body[:data][:ready] == false时触发重试,且调整最大重试次数为10次,希望能在发起请求时动态指定重试规则。
可行实现方案
方案1:全局重试中间件支持动态配置
修改全局的重试中间件,让它读取请求的自定义参数来覆盖默认重试逻辑和次数,无需创建新客户端即可实现特定请求的自定义重试:
首先更新客户端的重试配置:
client = Faraday.new(url: base_url) do |f| f.request :retry, { # 默认最大重试次数 max: 3, backoff_factor: 2, # 自定义重试判断逻辑:优先执行默认规则,再检查请求传入的自定义规则 retry_if: ->(env, exc) { # 保留默认的重试触发条件(网络错误、5xx响应) default_retry = Faraday::Request::Retry.new.default_retry_if.call(env, exc) # 读取请求中传入的自定义重试条件 custom_retry = env.request.options[:retry_options]&.fetch(:retry_if, ->(_,__) { false })&.call(env, exc) default_retry || custom_retry }, # 动态计算最大重试次数:优先使用请求传入的配置,否则用默认值 max: ->(env) { env.request.options[:retry_options]&.fetch(:max, 3) } } # 其他中间件保持不变 f.request :authorization, 'Bearer', -> { access_token } f.request :json f.response :json f.response :raise_error end
发起特定请求时,传入自定义的重试配置:
client.get("/wait-for-data") do |req| req.options[:retry_options] = { max: 10, retry_if: ->(env, _exc) { env.body.dig(:data, :ready) == false } } end
方案2:创建临时客户端处理特定请求
如果不想修改全局配置,可以复制原客户端的配置,移除原有重试中间件后添加自定义的重试规则,用这个临时客户端发起请求:
# 复制原客户端的连接配置 custom_client = client.dup do |f| # 移除原有的重试中间件 f.builder.delete(Faraday::Request::Retry) # 添加自定义的重试配置 f.request :retry, { max: 10, backoff_factor: 2, retry_if: ->(env, _exc) { env.body.dig(:data, :ready) == false } } end # 使用临时客户端发起请求 custom_client.get("/wait-for-data")
注意事项
- 因为配置了
response :json中间件,响应体已经被解析为Hash,所以可以直接通过env.body访问数据; raise_error中间件只会在响应状态码为4xx/5xx时抛出异常,成功响应不会触发异常,因此需要在retry_if中直接检查响应体内容来触发重试。
内容的提问来源于stack exchange,提问作者Narfanator
相关产品推荐
相关产品推荐

