Comparing changes

v0.2.0 v0.2.1
8 commits 6 files changed

Commits

483539f do not convert to json. mo 2018-11-11 05:00:32
fb531b8 revert constant name. mo 2018-11-11 04:36:05
aa895cf extract attemp method. mo 2018-11-11 04:34:05
7d5ff8c fix ruby 2.3, 2.4 syntax errors. mo 2018-11-11 03:42:19
049aedc start backoff at 100 ms mo 2018-11-11 03:01:21
dc61262 fix off by one on retry logic. mo 2018-11-11 02:39:33
2edc669 update homepage. mokha 2018-11-10 18:41:44
6c609de peace emoji mokha 2018-11-10 18:34:30
lib/net/hippie/client.rb
@@ -62,24 +62,21 @@ module Net
         execute(uri, request, &block)
       end
 
-      # attempt 1 -> delay 1 second
-      # attempt 2 -> delay 2 second
-      # attempt 3 -> delay 4 second
-      # attempt 4 -> delay 8 second
-      # attempt 5 -> delay 16 second
-      # attempt 6 -> delay 32 second
-      # attempt 7 -> delay 64 second
-      # attempt 8 -> delay 128 second
+      # attempt 1 -> delay 0.1 second
+      # attempt 2 -> delay 0.2 second
+      # attempt 3 -> delay 0.4 second
+      # attempt 4 -> delay 0.8 second
+      # attempt 5 -> delay 1.6 second
+      # attempt 6 -> delay 3.2 second
+      # attempt 7 -> delay 6.4 second
+      # attempt 8 -> delay 12.8 second
       def with_retry(retries: 3)
-        retries = 3 if retries <= 0
-        0.upto(retries) do |n|
-          return yield self
-        rescue *::Net::Hippie::CONNECTION_ERRORS => error
-          raise error if n >= retries
+        retries = 0 if retries.nil? || retries.negative?
 
-          delay = (2**n) + rand(0.5) # delay + jitter
-          warn("`#{error.message}` Retry: #{n + 1}/#{retries} Delay: #{delay}s")
-          sleep delay
+        0.upto(retries) do |n|
+          attempt(n, retries) do
+            return yield self
+          end
         end
       end
 
@@ -89,6 +86,16 @@ module Net
       attr_reader :verify_mode
       attr_reader :certificate, :key, :passphrase
 
+      def attempt(attempt, max)
+        yield
+      rescue *CONNECTION_ERRORS => error
+        raise error if attempt == max
+
+        delay = ((2**attempt) * 0.1) + Random.rand(0.05) # delay + jitter
+        warn("`#{error.message}` Retry: #{attempt + 1}/#{max} Delay: #{delay}s")
+        sleep delay
+      end
+
       def http_for(uri)
         http = Net::HTTP.new(uri.host, uri.port)
         http.read_timeout = read_timeout
lib/net/hippie/version.rb
@@ -2,6 +2,6 @@
 
 module Net
   module Hippie
-    VERSION = '0.2.0'
+    VERSION = '0.2.1'
   end
 end
test/net/client_test.rb
@@ -21,6 +21,7 @@ class ClientTest < Minitest::Test
   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_timeout.then
       .to_return(status: 200, body: { 'success' => 'true' }.to_json)
@@ -28,8 +29,21 @@ class ClientTest < Minitest::Test
       client.get(uri)
     end
     refute_nil response
-    assert_equal response.class, Net::HTTPOK
-    assert_equal('true', JSON.parse(response.body)['success'])
+    assert_equal Net::HTTPOK, response.class
+    assert_equal JSON.parse(response.body)['success'], 'true'
+  end
+
+  def test_exceeds_retries
+    uri = URI.parse('https://www.example.org/api/scim/v2/schemas')
+    WebMock.stub_request(:get, uri.to_s)
+      .to_timeout.then
+      .to_return(status: 200, body: { 'success' => 'true' }.to_json)
+
+    assert_raises Net::OpenTimeout do
+      subject.with_retry(retries: 0) do |client|
+        client.get(uri)
+      end
+    end
   end
 
   def test_get_with_string_uri
@@ -141,7 +155,7 @@ class ClientTest < Minitest::Test
   def test_put
     VCR.use_cassette('put_breaches') do
       uri = URI.parse('https://haveibeenpwned.com/api/breaches')
-      body = { command: 'echo hello' }.to_json
+      body = { command: 'echo hello' }
       response = subject.put(uri, body: body)
       refute_nil response
       assert_equal 'Congratulations!', JSON.parse(response.body)['Message']
@@ -151,7 +165,7 @@ class ClientTest < Minitest::Test
   def test_put_with_block_syntax
     VCR.use_cassette('put_breaches') do
       uri = URI.parse('https://haveibeenpwned.com/api/breaches')
-      body = { command: 'echo hello' }.to_json
+      body = { command: 'echo hello' }
       subject.put(uri, body: body) do |_request, response|
         @response = response
       end
.gitlab-ci.yml
@@ -9,4 +9,3 @@ before_script:
 ci:
   script:
     - bin/cibuild
-
.travis.yml
@@ -2,6 +2,8 @@ sudo: false
 language: ruby
 cache: bundler
 rvm:
-  - 2.5.1
+  - 2.3.8
+  - 2.4.5
+  - 2.5.3
 script:
   - bin/cibuild
net-hippie.gemspec
@@ -10,9 +10,9 @@ Gem::Specification.new do |spec|
   spec.authors       = ['mo']
   spec.email         = ['mo@mokhan.ca']
 
-  spec.summary       = 'net/http for hippies.'
-  spec.description   = 'net/http for hippies.'
-  spec.homepage      = 'https://www.mokhan.ca/'
+  spec.summary       = 'net/http for hippies. ☮️ '
+  spec.description   = 'net/http for hippies. ☮️ '
+  spec.homepage      = 'https://github.com/mokhan/net-hippie/'
   spec.license       = 'MIT'
 
   spec.files         = `git ls-files -z`.split("\x0").reject do |f|