Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Main function class method implementation. #13

Merged
merged 2 commits into from
Jul 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
take2 (0.0.5)
take2 (0.1.0)

GEM
remote: http://rubygems.org/
Expand Down
65 changes: 34 additions & 31 deletions lib/take2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,22 @@ def self.included(base)

class << self
attr_accessor :configuration
end

def self.config
@configuration ||= Configuration.new
end
def config
@configuration ||= Configuration.new
end

def self.reset(options = {})
@configuration = Configuration.new(options)
end
def reset(options = {})
@configuration = Configuration.new(options)
end

def self.local_defaults(options)
configuration.validate_options(options)
end
def local_defaults(options)
configuration.validate_options(options)
end

def self.configure
yield(config) if block_given?
def configure
yield(config) if block_given?
end
end

module InstanceMethods
Expand Down Expand Up @@ -56,8 +56,16 @@ module InstanceMethods
# end
#
# end
def call_api_with_retry(options = {}, &block)
self.class.call_api_with_retry(options, &block)
end

alias_method :with_retry, :call_api_with_retry
end

module ClassMethods
def call_api_with_retry(options = {})
config = self.class.retriable_configuration
config = retriable_configuration
config.merge!(Take2.local_defaults(options)) unless options.empty?
tries ||= config[:retries]
begin
Expand All @@ -74,25 +82,7 @@ def call_api_with_retry(options = {})
raise e
end
end
alias_method :with_retry, :call_api_with_retry

private

def rest(config, tries)
seconds = if config[:time_to_sleep].to_f > 0
config[:time_to_sleep].to_f
else
next_interval(config[:backoff_intervals], config[:retries], tries)
end
sleep(seconds)
end

def next_interval(intervals, retries, current)
intervals[retries - current]
end
end

module ClassMethods
# Sets number of retries.
#
# Example:
Expand Down Expand Up @@ -197,5 +187,18 @@ def response_status(response)
return response.status if response.respond_to?(:status)
response.status_code if response.respond_to?(:status_code)
end

def rest(config, tries)
seconds = if config[:time_to_sleep].to_f > 0
config[:time_to_sleep].to_f
else
next_interval(config[:backoff_intervals], config[:retries], tries)
end
sleep(seconds)
end

def next_interval(intervals, retries, current)
intervals[retries - current]
end
end
end
2 changes: 1 addition & 1 deletion lib/take2/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module Take2
VERSION = "0.0.5"
VERSION = "0.1.0"
end
186 changes: 92 additions & 94 deletions spec/take2_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,132 +151,130 @@ def wrath_the_gods_with(error)
raise error
end

context 'when raised with non retriable error' do
let(:error) { StandardError.new('Release the Kraken!!') }

describe 'class method' do
let(:retriable_error) { Net::HTTPRetriableError.new('Release the Kraken...many times!!', nil) }
before(:each) { @tries = 0 }

it 're raises the original error' do
expect do
object.call_api_with_retry { wrath_the_gods_with error }
end.to(raise_error(error.class))
it 'responds to the method' do
expect(klass).to respond_to(:call_api_with_retry)
end

it 'is not retried' do
it 'retries correct number of times' do
expect do
object.call_api_with_retry { wrath_the_gods_with error }
end.to(change { @tries }.from(0).to(1))
klass.call_api_with_retry { wrath_the_gods_with retriable_error }
end.to(change { @tries }.from(0).to(klass.retriable_configuration[:retries] + 1))
rescue
nil
end
end
describe 'instance method' do
context 'when raised with non retriable error' do
let(:error) { StandardError.new('Release the Kraken!!') }

context 'when raised with retriable error' do
let(:retriable_error) { Net::HTTPRetriableError.new('Release the Kraken...many times!!', nil) }

before(:each) { @tries = 0 }
before(:each) { @tries = 0 }

it 'retries correct number of times' do
expect do
object.call_api_with_retry { wrath_the_gods_with retriable_error }
end.to(change { @tries }.from(0).to(klass.retriable_configuration[:retries] + 1))
rescue
nil
end
it 're raises the original error' do
expect do
object.call_api_with_retry { wrath_the_gods_with error }
end.to(raise_error(error.class))
end

it 'calls the retry proc' do
expect(klass.retriable_configuration[:retry_proc])
.to(receive(:call)
.exactly(klass.retriable_configuration[:retries]))
begin
object.call_api_with_retry { wrath_the_gods_with retriable_error }
it 'is not retried' do
expect do
object.call_api_with_retry { wrath_the_gods_with error }
end.to(change { @tries }.from(0).to(1))
rescue
nil
end
end

it 'calls the retry_condition proc' do
expect(klass.retriable_configuration[:retry_condition_proc])
.to(receive(:call)
.exactly(klass.retriable_configuration[:retries]))
begin
object.call_api_with_retry { wrath_the_gods_with retriable_error }
context 'when raised with retriable error' do
let(:retriable_error) { Net::HTTPRetriableError.new('Release the Kraken...many times!!', nil) }

before(:each) { @tries = 0 }

it 'retries correct number of times' do
expect do
object.call_api_with_retry { wrath_the_gods_with retriable_error }
end.to(change { @tries }.from(0).to(klass.retriable_configuration[:retries] + 1))
rescue
nil
end
end

# it 'sleeps the correct amount of time' do
# allow_any_instance_of(Object).to(receive(:sleep).with(klass.retriable_configuration[:time_to_sleep]))
# begin
# object.call_api_with_retry { wrath_the_gods_with retriable_error }
# rescue
# nil
# end
# end
it 'calls the retry proc' do
expect(klass.retriable_configuration[:retry_proc])
.to(receive(:call)
.exactly(klass.retriable_configuration[:retries]))
begin
object.call_api_with_retry { wrath_the_gods_with retriable_error }
rescue
nil
end
end

it 're raises the original error' do
expect do
object.call_api_with_retry { wrath_the_gods_with retriable_error }
end.to(raise_error(retriable_error.class))
end
end
it 'calls the retry_condition proc' do
expect(klass.retriable_configuration[:retry_condition_proc])
.to(receive(:call)
.exactly(klass.retriable_configuration[:retries]))
begin
object.call_api_with_retry { wrath_the_gods_with retriable_error }
rescue
nil
end
end

context 'with custom options' do
let(:retriable_error) { Net::HTTPRetriableError.new('Release the Kraken...many times!!', nil) }
let(:new_retriable_error) { IOError.new('You shall not PASS!') }
it 're raises the original error' do
expect do
object.call_api_with_retry { wrath_the_gods_with retriable_error }
end.to(raise_error(retriable_error.class))
end
end

before(:each) { @tries = 0 }
context 'with custom options' do
let(:retriable_error) { Net::HTTPRetriableError.new('Release the Kraken...many times!!', nil) }
let(:new_retriable_error) { IOError.new('You shall not PASS!') }

it 'overwrites the :retries' do
expect do
object.call_api_with_retry(retries: 3) { wrath_the_gods_with retriable_error }
end.to(change { @tries }.from(0).to(4))
rescue
nil
end
before(:each) { @tries = 0 }

it 'overwrites the :retry_proc' do
new_proc = proc { 1**1 }
expect(new_proc).to(receive(:call).exactly(klass.retriable_configuration[:retries]))
begin
object.call_api_with_retry(retry_proc: new_proc) { wrath_the_gods_with retriable_error }
it 'overwrites the :retries' do
expect do
object.call_api_with_retry(retries: 3) { wrath_the_gods_with retriable_error }
end.to(change { @tries }.from(0).to(4))
rescue
nil
end
end

it 'overwrites the :retry_condition_proc' do
new_proc = proc { true }
expect(new_proc).to(receive(:call).exactly(klass.retriable_configuration[:retries]))
begin
object.call_api_with_retry(retry_condition_proc: new_proc) { wrath_the_gods_with retriable_error }
rescue
nil
it 'overwrites the :retry_proc' do
new_proc = proc { 1**1 }
expect(new_proc).to(receive(:call).exactly(klass.retriable_configuration[:retries]))
begin
object.call_api_with_retry(retry_proc: new_proc) { wrath_the_gods_with retriable_error }
rescue
nil
end
end
end

# it 'overwrites the :time_to_sleep' do
# allow_any_instance_of(Object).to(receive(:sleep).with(1.66))
# begin
# object.call_api_with_retry(time_to_sleep: 1.66) { wrath_the_gods_with retriable_error }
# rescue
# nil
# end
# end
it 'overwrites the :retry_condition_proc' do
new_proc = proc { true }
expect(new_proc).to(receive(:call).exactly(klass.retriable_configuration[:retries]))
begin
object.call_api_with_retry(retry_condition_proc: new_proc) { wrath_the_gods_with retriable_error }
rescue
nil
end
end

it 'overwrites the :retriable' do
expect do
object.call_api_with_retry(retriable: [new_retriable_error]) { wrath_the_gods_with retriable_error }
end.to(change { @tries }.from(0).to(1))
rescue
nil
end
it 'overwrites the :retriable' do
expect do
object.call_api_with_retry(retriable: [new_retriable_error]) { wrath_the_gods_with retriable_error }
end.to(change { @tries }.from(0).to(1))
rescue
nil
end

it 'raises ArgumentError if there are invalid keys' do
expect do
object.call_api_with_retry(invalid_key: :nope) { wrath_the_gods_with retriable_error }
end.to(raise_error(ArgumentError))
it 'raises ArgumentError if there are invalid keys' do
expect do
object.call_api_with_retry(invalid_key: :nope) { wrath_the_gods_with retriable_error }
end.to(raise_error(ArgumentError))
end
end
end
end
Expand Down