Completed
Push — master ( 0b4a0d...1f317b )
by John
50s
created

RetryUtil.initialize()   A

Complexity

Conditions 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
dl 0
loc 5
rs 9.4285
1
require "faraday/middleware"
2
3
module FaradayMiddleware
4
  module Request
5
    # Faraday middleware to handle HTTP Status 429 (rate limiting) / 503 (maintenance)
6
    class Retry < Faraday::Middleware
7
      attr_reader :retry_util
8
9
      def initialize(app, opts = {})
10
        super app
11
        @retry_util = FaradayMiddleware::Request::RetryUtil.new opts
12
      end
13
14
      def call(env)
15
        original_env = env.dup
16
        response = @app.call env
17
18
        retry_status = @retry_util.retry_status response.env[:status], response.env[:response_headers][:retry_after]
19
20
        if retry_status
21
          @app.call original_env
22
        else
23
          response
24
        end
25
      end
26
    end
27
  end
28
end
29
30
module FaradayMiddleware
31
  module Request
32
    # Standalone HTTP request retry utility class
33
    # Can be used outside of FaradayMiddleware, e.g.
34
    # when Faraday::UploadIO is used
35
    class RetryUtil
36
      DEFAULT_ERROR_CODES = [429, 503].freeze
37
      DEFAULT_RETRY_AFTER = 10
38
39
      attr_accessor :error_codes
40
      attr_accessor :retry_after
41
42
      def initialize(opts = {})
43
        @error_codes = opts[:error_codes] || DEFAULT_ERROR_CODES
44
        @retry_after = opts[:retry_after] || DEFAULT_RETRY_AFTER
45
        @logger = opts[:logger]
46
      end
47
48
      def retry_status(status, this_retry_after = nil)
49
        return false unless @error_codes.include? status
50
        seconds_left = (this_retry_after || @retry_after).to_i
51
        @logger.warn "You have been rate limited. Retrying in #{seconds_left} seconds..." if @logger
52
        seconds_left.times do |i|
53
          sleep 1
54
          time_left = seconds_left - i
55
          @logger.warn "#{time_left}..." if time_left > 0 && time_left % 5 == 0 && @logger
56
        end
57
        @logger.warn 'Retrying...' if @logger
58
        true
59
      end
60
    end
61
  end
62
end
63