简体   繁体   English

Ruby on Rails - 如果特定响应,法拉第重试请求?

[英]Ruby on Rails - Faraday retry request if specific response?

I've been struggling with Faraday and my Ruby on Rails app.我一直在为 Faraday 和我的 Ruby on Rails 应用程序苦苦挣扎。 An API controller in Rails creates a Model instance and sends this data serialized in JSON to an external app that will process the data and send a response with float number inside its response within a few seconds of the request. Rails 中的 API 控制器创建一个 Model 实例,并将此以 JSON 序列化的数据发送到外部应用程序,该应用程序将处理数据并在请求的几秒钟内在其响应中发送带有float的响应。

However, my app sometimes sends 50 individual requests and the external app may return a 502 error string as a response (please notice not an actual 502 HTTP error!!!).但是,我的应用有时会发送 50 个单独的请求,而外部应用可能会返回502错误字符串作为响应(请注意不是实际的 502 HTTP 错误!!!)。 I tried throttling my Faraday calls, but that made the external app go berserk, so now I'm trying to figure out how to re-submit a request if the response throws out this 502 string.我尝试限制我的法拉第调用,但这使外部应用程序变得疯狂,所以现在我试图弄清楚如果响应抛出这个502字符串,如何重新提交请求。 I haven't figured out how to write a Middleware for this, but it has not been necessary for now.我还没有想出如何为此编写中间件,但目前还没有必要。

Is there a way I can tell my method to resubmit the request to the external app if it receives a certain response inside its body?如果外部应用程序在其体内接收到某个响应,我是否可以告诉我的方法将请求重新提交给外部应用程序?

Here is my code (this method gets triggered for every request):这是我的代码(每个请求都会触发此方法):

Controller控制器

  def create
    cl = Model.where(
      attr1_id: params[:attr1_id],
      attr2_id: params[:attr2_id]
    ).first_or_initialize(params)
    cl.update(params)

    # Send new Model data (in JSON) in a request to external app
    cl_r = cl[:attr1_id]
    r = Some_model.find_by(id: cl_r)
    request = { :cl => cl, :r => r }

    # Send the request
    response = @conn.post do |req|
      req.url '/ml'
      req.headers['Content-Type'] = 'application/json'
      req.headers['password'] = 'password'
      req.body = request.to_json
    end

    # Get the response
    response_json = response.body
    response_json = response_json.gsub(/\s+/m, ' ').strip.split(" ")[1]

    # If the response (which takes a few seconds) returns a float inside its response body
    cl.update_attributes(response_attribute: response_json)
    # Else
    # Send the request that returned a 502 string inside the body to the external app again
    # End

    respond_with cl
  end

Thanks, your help is very appreciated!谢谢,非常感谢您的帮助!

You can try the code below你可以试试下面的代码

Faraday.new(your @conn params here if any) do |conn|
  conn.request :retry, max: 2, interval: 0.05,
                       interval_randomness: 0.5, backoff_factor: 2,
                       exceptions: [CustomException, 'Timeout::Error']

  response = conn.post do |req|
      req.url '/ml'
      req.headers['Content-Type'] = 'application/json'
      req.headers['password'] = 'password'
      req.body = request.to_json
    end

  raise CustomException if response.status == 502


  ...
end

you can check out the documentation for additional information.您可以查看文档以获取更多信息。

you can add你可以添加

builder.response :raise_error

to your connection builder to automatically have Faraday raise ClientError if the request is not successful (based on the response code, eg on 4xx/5xx codes).如果请求不成功(基于响应代码,例如 4xx/5xx 代码),连接到您的连接构建器以自动让 Faraday 引发ClientError

You also have to add Faraday::Error to your exceptions array in the retry config您还必须在retry配置中将Faraday::Error添加到您的异常数组中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM