retriable 1.4.1 → 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 03ab323e10afdc5d56ba1cb8dafe474b384ebab4
4
- data.tar.gz: b8018f10039fd5add022bd21bc89e3df94c742bf
3
+ metadata.gz: 75d7bf8633f7cf7fe492aa7d1b001d68a2389b34
4
+ data.tar.gz: 92a103a316a6c12a01e5374f4656e7be57cc3c76
5
5
  SHA512:
6
- metadata.gz: eb6d13ae6aef5945c071c28d122b2018c6faadc8a4567542a3b687e12905cd335c7542627b3be8d3d4b386189d31f9c0af0d3d214dc8d87047e0708d4606327b
7
- data.tar.gz: 3446c5920eb959cb60bd7a5cf4de8ace6df8480fbe80b82b526676557f5e0316780544b8986fb022a44a6d679a7a515931c236e67805d335fbf47938bf831735
6
+ metadata.gz: 6bb179a0ae1696e706d42b3a1769e67396238011363a5c152cd48a376fca099bf03db84413ca3e982cbadb13a14693a271d5eb2aa91dc4587301e2570490ada4
7
+ data.tar.gz: 9f4de38db13683ead4e8b78abf5be5ce200b942e453cbc94c6a934bacd3b5e31e4060be9803b03590c856ab41062c82cfe4a94924489eb7582027236e6df3d28
@@ -1,7 +1,10 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.2
4
- - 1.9.3
5
3
  - 2.0.0
6
- - jruby-19mode # JRuby in 1.9 mode
7
- - rbx-19mode
4
+ - 2.1.3
5
+ - jruby
6
+ - rbx
7
+
8
+ matrix:
9
+ allow_failures:
10
+ - rvm: rbx
@@ -1,3 +1,10 @@
1
+ ## 2.0.0.beta1
2
+ * Require ruby 2.0+.
3
+ * Default to random exponential backoff, removes the `interval` option. Exponential backoff is configurable via arguments.
4
+ * Allow configurable defaults via `#configure`.
5
+ * Change `Retriable.retriable` to `Retriable.retry`
6
+ * Support `max_elapsed_time` termination.
7
+
1
8
  ## 1.4.1
2
9
  * Fixes non kernel mode bug. Remove DSL class, move `#retriable` into Retriable module. Thanks @mkrogemann.
3
10
 
@@ -0,0 +1,14 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :minitest do
5
+ # with Minitest::Unit
6
+ watch(%r{^test/(.*)\/?test_(.*)\.rb})
7
+ watch(%r{^lib/retriable/(.*/)?([^/]+)\.rb}) { |m| "test/#{m[1]}/test_#{m[2]}.rb" }
8
+ watch(%r{^test/test_helper\.rb}) { 'test' }
9
+
10
+ # with Minitest::Spec
11
+ watch(%r{^spec/(.*)_spec\.rb})
12
+ watch(%r{^lib/retriable/(.+)\.rb}) { |m| "spec/#{m[1]}_spec.rb" }
13
+ watch(%r{^spec/spec_helper\.rb}) { 'spec' }
14
+ end
data/README.md CHANGED
@@ -2,9 +2,15 @@
2
2
 
3
3
  [![Build Status](https://secure.travis-ci.org/kamui/retriable.png)](http://travis-ci.org/kamui/retriable)
4
4
 
5
- Retriable is an simple DSL to retry a code block if an exception should be raised. This is especially useful when interacting external api/services or file system calls.
5
+ Retriable is an simple DSL to retry failed code blocks with randomized [exponential backoff](http://en.wikipedia.org/wiki/Exponential_backoff). This is especially useful when interacting external api/services or file system calls.
6
6
 
7
- ##Installation
7
+ ## Requirements
8
+
9
+ Ruby 2.0+
10
+
11
+ If you need 1.9.x support, use the [1.x branch](https://github.com/kamui/retriable/tree/1.x).
12
+
13
+ ## Installation
8
14
 
9
15
  via command line:
10
16
 
@@ -24,9 +30,22 @@ In your Gemfile:
24
30
  gem 'retriable'
25
31
  ```
26
32
 
27
- ##Usage
33
+ ## Usage
28
34
 
29
- Code in a retriable block will be retried if an exception is raised. By default, Retriable will rescue any exception inherited from `StandardError` (and `Timeout::Error`, which does not inherit from `StandardError` in ruby 1.8) and make 3 retry attempts before raising the last exception.
35
+ Code in a `Retriable.retry` block will be retried if an exception is raised. By default, Retriable will rescue any exception inherited from `StandardError`, make 3 retry attempts before raising the last exception, and also use randomized exponential backoff to calculate each succeeding attempt interval. The default interval table with 10 attempts looks like this (in seconds):
36
+
37
+ | request# | retry interval | randomized interval |
38
+ | -------- | -------------- | ------------------- |
39
+ | 1 | 0.5 | [0.25, 0.75] |
40
+ | 2 | 0.75 | [0.375, 1.125] |
41
+ | 3 | 1.125 | [0.562, 1.687] |
42
+ | 4 | 1.687 | [0.8435, 2.53] |
43
+ | 5 | 2.53 | [1.265, 3.795] |
44
+ | 6 | 3.795 | [1.897, 5.692] |
45
+ | 7 | 5.692 | [2.846, 8.538] |
46
+ | 8 | 8.538 | [4.269, 12.807] |
47
+ | 9 | 12.807 | [6.403, 19.210] |
48
+ | 10 | 19.210 | stop |
30
49
 
31
50
  ```ruby
32
51
  require 'retriable'
@@ -34,31 +53,53 @@ require 'retriable'
34
53
  class Api
35
54
  # Use it in methods that interact with unreliable services
36
55
  def get
37
- Retriable.retriable do
56
+ Retriable.retry do
38
57
  # code here...
39
58
  end
40
59
  end
41
60
  end
42
61
  ```
43
62
 
44
- ###Options
63
+ ### Options
45
64
 
46
65
  Here are the available options:
47
66
 
48
- `tries` (default: 3) - Number of attempts to make at running your code block
67
+ `max_tries` (default: 3) - Number of attempts to make at running your code block.
68
+
69
+ `base_interval` (default: 0.5) - The initial interval in seconds between attempts.
70
+
71
+ `max_interval` (default: 60) - The maximum interval in seconds that any attempt can climb to.
49
72
 
50
- `interval` (default: 0) - Number of seconds to sleep between attempts
73
+ `rand_factor` (default: 0.25) - The percent range above and below the next interval is randomized between. The calculation is calculated like this: `randomized_interval =
74
+ retry_interval * (random value in range [1 - randomization_factor, 1 + randomization_factor])`
75
+
76
+ `multiplier` (default: 1.5) - Each successive interval grows by this factor. A multipler of 1.5 means the next interval will be 1.5x the current interval.
77
+
78
+ `max_elapsed_time` (default: 900 (15 min)) - The maximum amount of total time that code is allowed to keep being retried
51
79
 
52
80
  `timeout` (default: 0) - Number of seconds to allow the code block to run before raising a Timeout::Error
53
81
 
54
- `on` (default: [StandardError, Timeout::Error]) - `StandardError` and `Timeout::Error` or array of exceptions to rescue for each attempt
82
+ `on` (default: [StandardError]) - An array of exceptions to rescue for each attempt, also accepts a single Exception type
55
83
 
56
84
  `on_retry` - (default: nil) - Proc to call after each attempt is rescued
57
85
 
58
- You can pass options via an options `Hash`. This example will only retry on a `Timeout::Error`, retry 3 times and sleep for a full second before each attempt.
86
+ ### Config
87
+
88
+ You can change the global defaults with a `#configure` block:
89
+
90
+ ```ruby
91
+ Retriable.configure do |c|
92
+ c.max_tries = 5
93
+ c.max_elapsed_time = 3600 # 1 hour
94
+ end
95
+ ```
96
+
97
+ ### Examples
98
+
99
+ `Retriable.retry` accepts custom arguments. This example will only retry on a `Timeout::Error`, retry 3 times and sleep for a full second before each attempt.
59
100
 
60
101
  ```ruby
61
- Retriable.retriable :on => Timeout::Error, :tries => 3, :interval => 1 do
102
+ Retriable.retry on: Timeout::Error, max_tries: 3, base_interval: 1 do
62
103
  # code here...
63
104
  end
64
105
  ```
@@ -66,7 +107,7 @@ end
66
107
  You can also specify multiple errors to retry on by passing an array of exceptions.
67
108
 
68
109
  ```ruby
69
- Retriable.retriable :on => [Timeout::Error, Errno::ECONNRESET] do
110
+ Retriable.retry on: [Timeout::Error, Errno::ECONNRESET] do
70
111
  # code here...
71
112
  end
72
113
  ```
@@ -74,7 +115,7 @@ end
74
115
  You can also specify a timeout if you want the code block to only make an attempt for X amount of seconds. This timeout is per attempt.
75
116
 
76
117
  ```ruby
77
- Retriable.retriable :timeout => 1 do
118
+ Retriable.retry timeout: 60 do
78
119
  # code here...
79
120
  end
80
121
  ```
@@ -82,42 +123,50 @@ end
82
123
  If you need millisecond units of time for the sleep or the timeout:
83
124
 
84
125
  ```ruby
85
- Retriable.retriable :interval => (200/1000.0), :timeout => (500/1000.0) do
126
+ Retriable.retry base_interval: (200/1000.0), timeout: (500/1000.0) do
86
127
  # code here...
87
128
  end
88
129
  ```
89
130
 
90
- ###Exponential Backoff
131
+ ### Turn off Exponential Backoff
91
132
 
92
- If you'd like exponential backoff, interval can take a Proc
133
+ Exponential backoff is enabled by default, if you want to simply execute code every second, you can do this:
93
134
 
94
135
  ```ruby
95
- # with exponential back-off - sleep 4, 16, 64, 256, give up
96
- Retriable.retryable :times => 4, :interval => lambda {|attempts| 4 ** attempts} do
136
+ Retriable.retryable base_interval: 1.0, multiplier: 1.0, rand_factor: 0.0 do
97
137
  # code here...
98
138
  end
99
139
  ```
100
- ###Callbacks
101
140
 
102
- Retriable also provides a callback called `:on_retry` that will run after an exception is rescued. This callback provides the number of `tries`, and the `exception` that was raised in the current attempt. As these are specified in a `Proc`, unnecessary variables can be left out of the parameter list.
141
+ If you don't want exponential backoff, but you still want some randomization between intervals, this code will run every 1 seconds with a randomization factor of 0.2, which means each interval will be a random value between 0.8 and 1.2 (1 second +/- 0.2):
142
+
143
+ ```ruby
144
+ Retriable.retryable base_interval: 1.0, multiplier: 1.0, rand_factor: 0.2 do
145
+ # code here...
146
+ end
147
+ ```
148
+
149
+ ### Callbacks
150
+
151
+ Retriable.retry also provides a callback called `:on_retry` that will run after an exception is rescued. This callback provides the `exception` that was raised in the current attempt, the `try_number`, the `elapsed_time` for all attempts so far, and the time in seconds of the `next_interval`. As these are specified in a `Proc`, unnecessary variables can be left out of the parameter list.
103
152
 
104
153
  ```ruby
105
- do_this_on_each_retry = Proc.new do |exception, tries|
106
- log "#{exception.class}: '#{exception.message}' - #{tries} attempts."}
154
+ do_this_on_each_retry = Proc.new do |exception, try_number, elapsed_time, next_interval|
155
+ log "#{exception.class}: '#{exception.message}' - #{try_number} attempts in #{elapsed_time} seconds and #{next_interval} seconds until the next attempt."}
107
156
  end
108
157
 
109
- Retriable.retriable :on_retry => do_this_on_each_retry do
158
+ Retriable.retry on_retry: do_this_on_each_retry do
110
159
  # code here...
111
160
  end
112
161
  ```
113
162
 
114
- ###Ensure/Else
163
+ ### Ensure/Else
115
164
 
116
165
  What if I want to execute a code block at the end, whether or not an exception was rescued ([ensure](http://ruby-doc.org/docs/keywords/1.9/Object.html#method-i-ensure))? Or, what if I want to execute a code block if no exception is raised ([else](http://ruby-doc.org/docs/keywords/1.9/Object.html#method-i-else))? Instead of providing more callbacks, I recommend you just wrap retriable in a begin/retry/else/ensure block:
117
166
 
118
167
  ```ruby
119
168
  begin
120
- Retriable.retriable do
169
+ Retriable.retry do
121
170
  # some code
122
171
  end
123
172
  rescue => e
@@ -129,9 +178,9 @@ ensure
129
178
  end
130
179
  ```
131
180
 
132
- ##Kernel Extension
181
+ ## Kernel Extension
133
182
 
134
- If you want to call `Retriable.retriable` without the `Retriable` module prefix and you don't mind extending `Kernel`,
183
+ If you want to call `Retriable.retry` without the `Retriable` module prefix and you don't mind extending `Kernel`,
135
184
  there is a kernel extension available for this.
136
185
 
137
186
  In your ruby script:
@@ -146,7 +195,7 @@ or in your Gemfile:
146
195
  gem 'retriable', require: 'retriable/core_ext/kernel'
147
196
  ```
148
197
 
149
- and then you can call `retriable` in any context like this:
198
+ and then you can call `#retriable` in any context like this:
150
199
 
151
200
  ```ruby
152
201
  retriable do
@@ -154,6 +203,6 @@ retriable do
154
203
  end
155
204
  ```
156
205
 
157
- ##Credits
206
+ ## Credits
158
207
 
159
208
  Retriable was originally forked from the retryable-rb gem by [Robert Sosinski](https://github.com/robertsosinski), which in turn originally inspired by code written by [Michael Celona](http://github.com/mcelona) and later assisted by [David Malin](http://github.com/dmalin). The [attempt](https://rubygems.org/gems/attempt) gem by Daniel J. Berger was also an inspiration.
data/Rakefile CHANGED
@@ -4,13 +4,13 @@ require 'bundler'
4
4
  Bundler::GemHelper.install_tasks
5
5
 
6
6
  require 'rake/testtask'
7
- task :default => :test
7
+ task default: :test
8
8
 
9
9
  desc "Run tests"
10
10
  task :test do
11
11
  Rake::TestTask.new do |t|
12
- t.libs << 'lib' << 'test'
13
- t.pattern = 'test/**/*_test.rb'
12
+ t.libs << 'lib' << 'spec'
13
+ t.pattern = 'spec/**/*_spec.rb'
14
14
  t.verbose = true
15
15
  end
16
16
  end
@@ -1,17 +1,69 @@
1
- require 'retriable/retry'
1
+ require 'timeout'
2
+ require 'retriable/config'
3
+ require 'retriable/version'
2
4
 
3
5
  module Retriable
4
6
  extend self
5
7
 
6
- def retriable(opts = {}, &block)
8
+ attr_accessor :config
9
+
10
+ def self.configure
11
+ self.config ||= Config.new
12
+ yield(config)
13
+ end
14
+
15
+ def retry(
16
+ max_tries: config.max_tries,
17
+ base_interval: config.base_interval,
18
+ max_interval: config.max_interval,
19
+ rand_factor: config.rand_factor,
20
+ multiplier: config.multiplier,
21
+ max_elapsed_time: config.max_elapsed_time,
22
+ timeout: config.timeout,
23
+ on: config.on,
24
+ on_retry: config.on_retry,
25
+ &block)
26
+
7
27
  raise LocalJumpError unless block_given?
8
28
 
9
- Retry.new do |r|
10
- r.tries = opts[:tries] if opts[:tries]
11
- r.on = opts[:on] if opts[:on]
12
- r.interval = opts[:interval] if opts[:interval]
13
- r.timeout = opts[:timeout] if opts[:timeout]
14
- r.on_retry = opts[:on_retry] if opts[:on_retry]
15
- end.perform(&block)
29
+ attempt = 0
30
+ start_time = Time.now
31
+ interval = base_interval
32
+
33
+ begin
34
+ attempt += 1
35
+ if timeout
36
+ Timeout::timeout(timeout) { return block.call(attempt) }
37
+ else
38
+ return block.call(attempt)
39
+ end
40
+ rescue *[*on] => exception
41
+ raise if attempt >= max_tries
42
+
43
+ return if (Time.now - start_time) > max_elapsed_time
44
+
45
+ interval = randomized_interval(rand_factor, interval)
46
+
47
+ on_retry.call(exception, attempt, Time.now - start_time, interval) if on_retry
48
+
49
+ sleep interval if interval > 0 && config.sleep_disabled != true
50
+
51
+ interval = if interval >= (max_interval / multiplier)
52
+ max_interval
53
+ else
54
+ interval * multiplier
55
+ end
56
+
57
+ retry
58
+ end
59
+ end
60
+
61
+ private
62
+ def randomized_interval(rand_factor, interval)
63
+ return interval if rand_factor == 0
64
+ delta = rand_factor * interval * 1.0
65
+ min_interval = interval - delta
66
+ max_interval = interval + delta
67
+ rand(min_interval..max_interval)
16
68
  end
17
69
  end
@@ -0,0 +1,27 @@
1
+ module Retriable
2
+ class Config
3
+ attr_accessor :sleep_disabled
4
+ attr_accessor :max_tries
5
+ attr_accessor :base_interval
6
+ attr_accessor :max_interval
7
+ attr_accessor :rand_factor
8
+ attr_accessor :multiplier
9
+ attr_accessor :max_elapsed_time
10
+ attr_accessor :timeout
11
+ attr_accessor :on
12
+ attr_accessor :on_retry
13
+
14
+ def initialize
15
+ @sleep_disabled = false
16
+ @max_tries = 3
17
+ @base_interval = 0.5
18
+ @max_interval = 60
19
+ @rand_factor = 0.5
20
+ @multiplier = 1.5
21
+ @max_elapsed_time = 900 # 15 minn
22
+ @timeout = nil
23
+ @on = [StandardError]
24
+ @on_retry = nil
25
+ end
26
+ end
27
+ end
@@ -1,6 +1,7 @@
1
1
  require 'retriable'
2
2
 
3
3
  module Kernel
4
- include Retriable
5
- private :retriable
4
+ def retriable(opts={}, &block)
5
+ Retriable.retry(opts, &block)
6
+ end
6
7
  end
@@ -1,3 +1,3 @@
1
1
  module Retriable
2
- VERSION = '1.4.1'
2
+ VERSION = '2.0.0.beta1'
3
3
  end
@@ -10,8 +10,9 @@ Gem::Specification.new do |s|
10
10
  s.authors = ["Jack Chu"]
11
11
  s.email = ["jack@jackchu.com"]
12
12
  s.homepage = %q{http://github.com/kamui/retriable}
13
- s.summary = %q{Retriable is an simple DSL to retry a code block if an exception should be raised.}
14
- s.description = %q{Retriable is an simple DSL to retry a code block if an exception should be raised. This is especially useful when interacting external api/services or file system calls.}
13
+ s.summary = %q{Retriable is an simple DSL to retry failed code blocks with randomized exponential backoff}
14
+ s.description = %q{Retriable is an simple DSL to retry failed code blocks with randomized exponential backoff. This is especially useful when interacting external api/services or file system calls.
15
+ }
15
16
  s.license = "MIT"
16
17
 
17
18
  s.rubyforge_project = "retriable"
@@ -23,4 +24,8 @@ Gem::Specification.new do |s|
23
24
 
24
25
  s.add_development_dependency 'rake'
25
26
  s.add_development_dependency 'minitest', '>= 5.0'
27
+ s.add_development_dependency 'minitest-focus'
28
+ s.add_development_dependency 'pry'
29
+ s.add_development_dependency 'guard'
30
+ s.add_development_dependency 'guard-minitest'
26
31
  end
@@ -0,0 +1,111 @@
1
+ require_relative 'spec_helper'
2
+
3
+ class TestError < Exception; end
4
+
5
+ describe Retriable do
6
+ subject do
7
+ Retriable
8
+ end
9
+
10
+ before do
11
+ Retriable.configure do |c|
12
+ c.sleep_disabled = true
13
+ end
14
+ end
15
+
16
+ it 'raises a LocalJumpError if retry is not given a block' do
17
+ lambda do
18
+ subject.retry on: EOFError
19
+ end.must_raise LocalJumpError
20
+ end
21
+
22
+ describe 'retry block of code raising EOFError with no arguments' do
23
+ before do
24
+ @attempts = 0
25
+
26
+ subject.retry do
27
+ @attempts += 1
28
+ raise EOFError.new if @attempts < 3
29
+ end
30
+ end
31
+
32
+ it 'uses exponential backoff' do
33
+ @attempts.must_equal 3
34
+ end
35
+ end
36
+
37
+ it 'retry on custom exception and re-raises the exception' do
38
+ lambda do
39
+ subject.retry on: TestError do
40
+ raise TestError.new
41
+ end
42
+ end.must_raise TestError
43
+ end
44
+
45
+ it 'retry with 10 max tries' do
46
+ attempts = 0
47
+
48
+ subject.retry(
49
+ max_tries: 10
50
+ ) do
51
+ attempts += 1
52
+ raise EOFError.new if attempts < 10
53
+ end
54
+
55
+ attempts.must_equal 10
56
+ end
57
+
58
+ describe 'retries with an on_retry handler, 6 max retries, and a 0.0 rand_factor' do
59
+ before do
60
+ max_tries = 6
61
+ @attempts = 0
62
+ @time_table = {}
63
+
64
+ handler = Proc.new do |exception, attempt, elapsed_time, next_interval|
65
+ exception.class.must_equal ArgumentError
66
+ @time_table[attempt] = next_interval
67
+ end
68
+
69
+ Retriable.retry(
70
+ on: [EOFError, ArgumentError],
71
+ on_retry: handler,
72
+ rand_factor: 0.0,
73
+ max_tries: max_tries
74
+ ) do
75
+ @attempts += 1
76
+ raise ArgumentError.new if @attempts < max_tries
77
+ end
78
+ end
79
+
80
+ it 'makes 6 attempts' do
81
+ @attempts.must_equal 6
82
+ end
83
+
84
+ it 'applies a non-randomized exponential backoff to each attempt' do
85
+ @time_table.must_equal({
86
+ 1 => 0.5,
87
+ 2 => 0.75,
88
+ 3 => 1.125,
89
+ 4 => 1.6875,
90
+ 5 => 2.53125
91
+ })
92
+ end
93
+ end
94
+
95
+ it 'can call #retriable in the global' do
96
+ lambda do
97
+ retriable do
98
+ puts 'should raise NoMethodError'
99
+ end
100
+ end.must_raise NoMethodError
101
+
102
+ require_relative '../lib/retriable/core_ext/kernel'
103
+
104
+ i = 0
105
+ retriable do
106
+ i += 1
107
+ raise EOFError.new if i < 3
108
+ end
109
+ i.must_equal 3
110
+ end
111
+ end
@@ -0,0 +1,5 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/focus'
3
+ require 'pry'
4
+
5
+ require_relative '../lib/retriable'
@@ -0,0 +1,27 @@
1
+ box: wercker/rvm
2
+ # Build definition
3
+ build:
4
+ # The steps that will be executed on build
5
+ # See the Ruby section on the wercker devcenter:
6
+ # http://devcenter.wercker.com/articles/languages/ruby.html
7
+ steps:
8
+ # Uncomment this to force RVM to use a specific Ruby version
9
+ # - rvm-use:
10
+ # version: 2.1.0
11
+
12
+ # A step that executes `bundle install` command
13
+ - bundle-install
14
+
15
+ # A custom script step, name value is used in the UI
16
+ # and the code value contains the command that get executed
17
+ - script:
18
+ name: echo ruby information
19
+ code: |
20
+ echo "ruby version $(ruby --version) running"
21
+ echo "from location $(which ruby)"
22
+ echo -p "gem list: $(gem list)"
23
+
24
+ # Add more steps here:
25
+ - script:
26
+ name: rake
27
+ code: bundle exec rake
metadata CHANGED
@@ -1,65 +1,123 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: retriable
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 2.0.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jack Chu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-06 00:00:00.000000000 Z
11
+ date: 2014-09-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '5.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '5.0'
41
- description: Retriable is an simple DSL to retry a code block if an exception should
42
- be raised. This is especially useful when interacting external api/services or file
43
- system calls.
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest-focus
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard-minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: |
98
+ Retriable is an simple DSL to retry failed code blocks with randomized exponential backoff. This is especially useful when interacting external api/services or file system calls.
44
99
  email:
45
100
  - jack@jackchu.com
46
101
  executables: []
47
102
  extensions: []
48
103
  extra_rdoc_files: []
49
104
  files:
50
- - .gitignore
51
- - .travis.yml
105
+ - ".gitignore"
106
+ - ".travis.yml"
52
107
  - CHANGELOG.md
53
108
  - Gemfile
109
+ - Guardfile
54
110
  - LICENSE
55
111
  - README.md
56
112
  - Rakefile
57
113
  - lib/retriable.rb
114
+ - lib/retriable/config.rb
58
115
  - lib/retriable/core_ext/kernel.rb
59
- - lib/retriable/retry.rb
60
116
  - lib/retriable/version.rb
61
117
  - retriable.gemspec
62
- - test/retriable_test.rb
118
+ - spec/retriable_spec.rb
119
+ - spec/spec_helper.rb
120
+ - wercker.yml
63
121
  homepage: http://github.com/kamui/retriable
64
122
  licenses:
65
123
  - MIT
@@ -70,20 +128,21 @@ require_paths:
70
128
  - lib
71
129
  required_ruby_version: !ruby/object:Gem::Requirement
72
130
  requirements:
73
- - - '>='
131
+ - - ">="
74
132
  - !ruby/object:Gem::Version
75
133
  version: '0'
76
134
  required_rubygems_version: !ruby/object:Gem::Requirement
77
135
  requirements:
78
- - - '>='
136
+ - - ">"
79
137
  - !ruby/object:Gem::Version
80
- version: '0'
138
+ version: 1.3.1
81
139
  requirements: []
82
140
  rubyforge_project: retriable
83
- rubygems_version: 2.0.7
141
+ rubygems_version: 2.2.2
84
142
  signing_key:
85
143
  specification_version: 4
86
- summary: Retriable is an simple DSL to retry a code block if an exception should be
87
- raised.
144
+ summary: Retriable is an simple DSL to retry failed code blocks with randomized exponential
145
+ backoff
88
146
  test_files:
89
- - test/retriable_test.rb
147
+ - spec/retriable_spec.rb
148
+ - spec/spec_helper.rb
@@ -1,44 +0,0 @@
1
- require 'timeout'
2
-
3
- module Retriable
4
- class Retry
5
- attr_accessor :tries
6
- attr_accessor :interval
7
- attr_accessor :timeout
8
- attr_accessor :on
9
- attr_accessor :on_retry
10
-
11
- def initialize
12
- @tries = 3
13
- @interval = 0
14
- @timeout = nil
15
- @on = [StandardError, Timeout::Error]
16
- @on_retry = nil
17
-
18
- yield self if block_given?
19
- end
20
-
21
- def perform
22
- count = 0
23
- begin
24
- if @timeout
25
- Timeout::timeout(@timeout) { yield }
26
- else
27
- yield
28
- end
29
- rescue *[*on] => exception
30
- @tries -= 1
31
- if @tries > 0
32
- count += 1
33
- @on_retry.call(exception, count) if @on_retry
34
- sleep_for = @interval.respond_to?(:call) ? @interval.call(count) : @interval
35
- sleep sleep_for if sleep_for > 0
36
-
37
- retry
38
- else
39
- raise
40
- end
41
- end
42
- end
43
- end
44
- end
@@ -1,84 +0,0 @@
1
- require 'retriable'
2
- require 'minitest/autorun'
3
-
4
- class RetriableTest < Minitest::Test
5
- def test_raise_no_block
6
- assert_raises LocalJumpError do
7
- Retriable.retriable :on => StandardError
8
- end
9
- end
10
-
11
- def test_without_arguments
12
- i = 0
13
-
14
- Retriable.retriable do
15
- i += 1
16
- raise StandardError.new
17
- end
18
- rescue StandardError
19
- assert_equal 3, i
20
- end
21
-
22
- def test_with_one_exception_and_two_tries
23
- i = 0
24
-
25
- Retriable.retriable :on => EOFError, :tries => 2 do
26
- i += 1
27
- raise EOFError.new
28
- end
29
-
30
- rescue EOFError
31
- assert_equal i, 2
32
- end
33
-
34
- def test_with_arguments
35
- i = 0
36
-
37
- on_retry = Proc.new do |exception, tries|
38
- assert_equal exception.class, ArgumentError
39
- assert_equal i, tries
40
- end
41
-
42
- Retriable.retriable :on => [EOFError, ArgumentError], :on_retry => on_retry, :tries => 5, :sleep => 0.2 do |h|
43
- i += 1
44
- raise ArgumentError.new
45
- end
46
-
47
- rescue ArgumentError
48
- assert_equal 5, i
49
- end
50
-
51
- def test_with_interval_proc
52
- was_called = false
53
-
54
- sleeper = Proc.new do |attempts|
55
- was_called = true
56
- attempts
57
- end
58
-
59
- Retriable.retriable :on => EOFError, :interval => sleeper do |h|
60
- raise EOFError.new
61
- end
62
- rescue
63
- assert_equal was_called, true
64
- end
65
-
66
- def test_kernel_ext
67
- assert_raises NoMethodError do
68
- retriable do
69
- puts 'should raise NoMethodError'
70
- end
71
- end
72
-
73
- require 'retriable/core_ext/kernel'
74
- i = 0
75
-
76
- retriable do
77
- i += 1
78
- raise StandardError.new
79
- end
80
-
81
- rescue StandardError
82
- assert_equal 3, i
83
- end
84
- end