Commit bd4e243

mokha <mokha@cisco.com>
2018-11-10 17:09:33
add retry.
1 parent a247acd
Changed files (3)
lib/net/hippie/client.rb
@@ -12,6 +12,7 @@ module Net
 
       attr_accessor :mapper
       attr_accessor :read_timeout
+      attr_accessor :logger
 
       def initialize(
         certificate: nil,
@@ -27,6 +28,7 @@ module Net
         @passphrase = passphrase
         @read_timeout = 30
         @verify_mode = verify_mode
+        @logger = Net::Hippie.logger
       end
 
       def execute(uri, request)
@@ -60,6 +62,16 @@ module Net
         execute(uri, request, &block)
       end
 
+      def with_retry(retries: 3)
+        retries.downto(0) do |n|
+          return yield self
+        rescue *::Net::Hippie::CONNECTION_ERRORS => error
+          logger.error("Retry Attempt: #{n}")
+          logger.error(error)
+          raise error if n.zero?
+        end
+      end
+
       private
 
       attr_reader :default_headers
@@ -71,7 +83,7 @@ module Net
         http.read_timeout = read_timeout
         http.use_ssl = uri.scheme == 'https'
         http.verify_mode = verify_mode
-        http.set_debug_output(Net::Hippie.logger)
+        http.set_debug_output(logger)
         apply_client_tls_to(http)
         http
       end
lib/net/hippie.rb
@@ -14,6 +14,14 @@ require 'net/hippie/api'
 module Net
   # net/http for hippies.
   module Hippie
+    CONNECTION_ERRORS = [
+      EOFError,
+      Errno::ECONNRESET,
+      Errno::EINVAL,
+      Net::ProtocolError,
+      Timeout::Error
+    ].freeze
+
     def self.logger
       @logger ||= Logger.new(STDOUT)
     end
test/net/client_test.rb
@@ -6,6 +6,7 @@ class ClientTest < Minitest::Test
   def initialize(*args)
     super
     @subject = Net::Hippie::Client.new
+    @subject.logger = Logger.new('/dev/null')
   end
 
   def test_get
@@ -17,6 +18,19 @@ class ClientTest < Minitest::Test
     end
   end
 
+  def test_get_with_retry
+    uri = URI.parse('https://www.example.org/api/scim/v2/schemas')
+    WebMock.stub_request(:get, uri.to_s)
+      .to_timeout.then
+      .to_timeout.then
+      .to_return(status: 200, body: { 'success' => 'true' }.to_json)
+    response = subject.with_retry(retries: 3) do |client|
+      client.get(uri)
+    end
+    refute_nil response
+    assert_equal('true', JSON.parse(response.body)['success'])
+  end
+
   def test_get_with_string_uri
     VCR.use_cassette('get_breaches') do
       response = subject.get('https://haveibeenpwned.com/api/breaches')