【问题标题】:Unexpected behaviour with Faraday::ConnectionFailedFaraday::ConnectionFailed 的意外行为
【发布时间】:2020-03-29 06:28:33
【问题描述】:

我正在为从Faraday::ConnectionFailedFaraday::TimeoutError 抢救的API 编写一个客户端,以重试相同的方法MAX_RETRIES 次。

这是涉及的主要方法:

def benchmark_request(path)
  retries ||= 0
  request_start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)

  response = yield

  total_request_seconds = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - request_start_time)
  Rails.logger.info "client request took (#{total_request_seconds}s): #{ENV['API_PATH_PREFIX']}#{path}"

  response
rescue Faraday::ConnectionFailed, Faraday::TimeoutError => e
  retries += 1
  retry if retries <= MAX_RETRIES
end

调用的方法是:

 def get(path, params = {})
   benchmark_request(path) { token.get("#{ENV['API_PATH_PREFIX']}#{path}", params) }
 end

token.get 来自使用Faradayoauth2 gem

这是有趣的部分。 我写了 2 个规范,每个要处理的异常都有 1 个。

context 'when the endpoint raises a ConnectionFailed' do
  let(:token_expires_at) { 1.hour.from_now.to_i }
  let(:response_body) { '' }
  let(:response_status) { 200 }

  before do
    allow(token).to receive(:get).and_raise(Faraday::ConnectionFailed)
    described_class.get(api_endpoint)
  end

  it 'is called MAX_RETRIES times' do
    expect(token).to have_received(:get).exactly(3).times
  end
end

context 'when the endpoint raises a TimeoutError' do
  let(:token_expires_at) { 1.hour.from_now.to_i }
  let(:response_body) { '' }
  let(:response_status) { 200 }

  before do
    allow(token).to receive(:get).and_raise(Faraday::TimeoutError)
    described_class.get(api_endpoint)
  end

  it 'is called MAX_RETRIES times' do
    expect(token).to have_received(:get).exactly(3).times
  end
end

测试测试ConnectionFailed 失败,测试测试TimeoutError 为绿色。 引发的异常是:

1) Client::Base.get when the endpoint raises a ConnectionFailed is called MAX_RETRIES times
 Failure/Error: token.get(path, params)

 ArgumentError:
   wrong number of arguments (given 0, expected 1..2)
 # /home/ngw/.rvm/gems/ruby-2.6.2/gems/faraday-0.15.4/lib/faraday/error.rb:7:in `initialize'
 # ./app/lib/client/base.rb:13:in `get'
 # ./spec/lib/client/base_spec.rb:111:in `block (4 levels) in <top (required)>'

这显然是关于异常是如何初始化的。

有人知道吗?

【问题讨论】:

    标签: ruby api http faraday


    【解决方案1】:

    这是因为 Farady::ConnectionFailed 继承自 Faraday::Error 类,该类在其def initialize 中至少需要一个参数。检查来源here (Error)here (ConnectionFailed)

    TimeoutError 有效,因为它为 exc 设置了默认值 "timeout" here

    乍一看很难发现,我完全理解你也迷路了。

    正如@MikeRogers0 在他的解决方案中提到的,您必须在and_raise 中使用第二个参数。

    希望这个答案对您有所帮助。

    【讨论】:

      【解决方案2】:
      before do
         allow(token).to receive(:get).and_raise(Faraday::TimeoutError, 'execution expired')
        described_class.get(api_endpoint)
      end
      

      我通过将second argument 传递给and_raise 方法解决了这个问题。我认为这是因为法拉第的异常类略有不同。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-28
        • 2018-10-25
        • 2019-10-24
        • 2016-02-07
        • 1970-01-01
        • 2019-06-13
        • 1970-01-01
        相关资源
        最近更新 更多