retry_upto 1.0 → 1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. data/README.md +42 -19
  2. data/lib/retry_upto.rb +2 -52
  3. data/test/retry_upto_test.rb +35 -19
  4. metadata +44 -78
data/README.md CHANGED
@@ -1,44 +1,67 @@
1
1
  # retry_upto: retry with steroids
2
2
 
3
+ If you need to use `retry` in ruby, you probably want to retry some code only a **maximum number of times**,
4
+ and sometimes **wait a bit** between the attempts to avoid external resources hiccups or usage limits.
5
+
6
+ Therefore **Your Important Code** ends surrounded by counters, conditions and calls to `sleep`.
7
+
8
+ This gem deals elegantly with this common scenario:
9
+
10
+ 5.times.retry do
11
+ # Your Important Code
12
+ end
13
+
14
+ Keep reading to see all the options available.
15
+
3
16
  ## Usage
4
17
 
5
- Basic usage
18
+ ### Basic usage
6
19
 
7
- - retries up to 5 times catching any exception, doesn't wait between attempts:
20
+ Retries up to 5 times catching any exception, doesn't wait between attempts:
8
21
 
9
- retry_upto(5) do ... end
22
+ retry_upto(5)
10
23
 
11
- Waiting time between attempts
24
+ ### Waiting time between attempts
12
25
 
13
- - retries up to 5 times, waits 2 seconds between attempts:
26
+ Retries up to 5 times, waits 2 seconds between attempts:
14
27
 
15
- retry_upto(5, :interval => 2) do ... end
28
+ retry_upto(5, :interval => 2)
16
29
 
17
- Varying waiting time between attempts
30
+ ### Varying waiting time between attempts
18
31
 
19
- - retries up to 5 times, waits 1 second after the first attempt and increases
20
- the time between the following attempts (2, 4, 8, ...):
32
+ Retries up to 5 times, waits 1 second after the first attempt and increases
33
+ the time between the following attempts (2, 4, 8, ...):
21
34
 
22
- retry_upto(5, :interval => 1, :growth => 2) do ... end
35
+ retry_upto(5, :interval => 1, :growth => 2)
23
36
 
24
- - retries up to 5 times, waits 1 second after the first attempt and decreases
25
- the time between the following attempts (0.5, 0.25, 0.125, ...):
37
+ Retries up to 5 times, waits 1 second after the first attempt and decreases
38
+ the time between the following attempts (0.5, 0.25, 0.125, ...):
26
39
 
27
- retry_upto(5, :interval => 1, :growth => 0.5) do ... end
40
+ retry_upto(5, :interval => 1, :growth => 0.5)
28
41
 
29
- - retries up to 5 times, waits 1 second after the first attempt and increases
30
- randomly the time between the following attempts:
42
+ Retries up to 5 times, waits 1 second after the first attempt and increases
43
+ randomly the time between the following attempts:
31
44
 
32
- retry_upto(5, :interval => 1, :growth => lambda{ |x| x + rand(3) } ) do ... end
45
+ retry_upto(5, :interval => 1, :growth => lambda{ |x| x + rand(3) } )
33
46
 
34
- Retrying only when certain Exceptions get raised
47
+ ### Retrying only when certain Exceptions get raised
35
48
 
36
- - retries up to 5 times only after a ZeroDivisionError, raising any other Exception:
49
+ Retries up to 5 times only after a ZeroDivisionError, raising any other Exception:
37
50
 
38
- retry_upto(5, :rescue => ZeroDivisionError) do ... end
51
+ retry_upto(5, :rescue => ZeroDivisionError)
39
52
 
40
53
  All the options described above can be combined together.
41
54
 
55
+ ### More sugar!
56
+
57
+ In ruby 1.9, the `Enumerator` class gets enhanced to use `retry_upto` this way:
58
+
59
+ 5.times.retry
60
+
61
+ And yes, this accepts the same options:
62
+
63
+ 5.times.retry(:interval => 10)
64
+
42
65
  ## License
43
66
 
44
67
  See the LICENSE file included in the distribution.
data/lib/retry_upto.rb CHANGED
@@ -1,49 +1,8 @@
1
- # retry with steroids
2
- #
3
- # Basic usage:
4
- #
5
- # - retries up to 5 times catching any exception, doesn't wait between attempts
6
- #
7
- # retry_upto(5) do ... end
8
- #
9
- #
10
- # Waiting time between attempts:
11
- #
12
- # - retries up to 5 times, waits 2 seconds between attempts
13
- #
14
- # retry_upto(5, :interval => 2) do ... end
15
- #
16
- #
17
- # Varying waiting time between attempts:
18
- #
19
- # - retries up to 5 times, waits 1 second after the first attempt and increases
20
- # the time between the following attempts (2, 4, 8, ...)
21
- #
22
- # retry_upto(5, :interval => 1, :growth => 2) do ... end
23
- #
24
- # - retries up to 5 times, waits 1 second after the first attempt and decreases
25
- # the time between the following attempts (0.5, 0.25, 0.125, ...)
26
- #
27
- # retry_upto(5, :interval => 1, :growth => 0.5) do ... end
28
- #
29
- # - retries up to 5 times, waits 1 second after the first attempt and increases
30
- # randomly the time between the following attempts
31
- #
32
- # retry_upto(5, :interval => 1, :growth => lambda{ |x| x + rand(3) } ) do ... end
33
- #
34
- #
35
- # Retrying only when certain Exceptions get raised:
36
- #
37
- # - retries up to 5 times only after a ZeroDivisionError, raising any other Exception
38
- #
39
- # retry_upto(5, :rescue => ZeroDivisionError) do ... end
40
- #
41
- #
42
- # All the described options can be combined together.
1
+ # See README.md for usage explanations
43
2
 
44
3
  def retry_upto(max_retries = 1, options = {})
45
4
  yield
46
- rescue (options[:rescue] || Exception)
5
+ rescue *(options[:rescue] || Exception)
47
6
  raise if (max_retries -= 1) == 0
48
7
  sleep(options[:interval] || 0)
49
8
  if options[:growth].respond_to?('*')
@@ -54,15 +13,6 @@ rescue (options[:rescue] || Exception)
54
13
  retry
55
14
  end
56
15
 
57
-
58
-
59
- # Extends enumerator to allow usage like:
60
- #
61
- # 5.times.retry do
62
- # ...
63
- # end
64
- #
65
-
66
16
  class Enumerator
67
17
  def retry(options = {}, &blk)
68
18
  retry_upto(self.count, options, &blk)
@@ -3,15 +3,25 @@ require './test/test_helper'
3
3
  class Retry_uptoTest < MiniTest::Unit::TestCase
4
4
 
5
5
  class FooError < Exception; end
6
+ class BarError < Exception; end
6
7
 
7
- # raises ZeroDivisionError in the two first hits
8
8
  class Target
9
- attr_accessor :hits
10
- def initialize; @hits = 0; end
9
+ attr_accessor :foos, :bars
10
+ def initialize
11
+ @foos = 0
12
+ @bars = 0
13
+ end
14
+
15
+ # raises FooError only in the two first calls
16
+ def foo!
17
+ @foos += 1
18
+ raise FooError if @foos < 3
19
+ end
11
20
 
12
- def hit!
13
- @hits += 1
14
- raise FooError if @hits < 3
21
+ # raises BarError only in the two first calls
22
+ def bar!
23
+ @bars += 1
24
+ raise BarError if @bars < 3
15
25
  end
16
26
  end
17
27
 
@@ -23,26 +33,26 @@ class Retry_uptoTest < MiniTest::Unit::TestCase
23
33
 
24
34
  def test_retries_one_time_by_default_without_capturing_the_exception
25
35
  assert_raises(FooError) do
26
- retry_upto{ @target.hit! }
36
+ retry_upto{ @target.foo! }
27
37
  end
28
- assert_equal 1, @target.hits
38
+ assert_equal 1, @target.foos
29
39
  end
30
40
 
31
41
  def test_retries_the_desired_number_of_attempts
32
- retry_upto(3){ @target.hit! }
33
- assert_equal 3, @target.hits
42
+ retry_upto(3){ @target.foo! }
43
+ assert_equal 3, @target.foos
34
44
  end
35
45
 
36
46
  # interval between attempts
37
47
 
38
48
  def test_there_is_no_interval_between_attempts_by_default
39
49
  self.expects(:sleep).times(2).with(0).returns(nil)
40
- retry_upto(3){ @target.hit! }
50
+ retry_upto(3){ @target.foo! }
41
51
  end
42
52
 
43
53
  def test_interval_between_attempts_can_be_customized
44
54
  self.expects(:sleep).times(2).with(5).returns(nil)
45
- retry_upto(3, :interval => 5){ @target.hit! }
55
+ retry_upto(3, :interval => 5){ @target.foo! }
46
56
  end
47
57
 
48
58
  # interval growth between attempts
@@ -50,42 +60,48 @@ class Retry_uptoTest < MiniTest::Unit::TestCase
50
60
  def test_inverval_can_be_multiplied_by_an_integer_growth
51
61
  self.expects(:sleep).times(1).with(5)
52
62
  self.expects(:sleep).times(1).with(15)
53
- retry_upto(3, :interval => 5, :growth => 3){ @target.hit! }
63
+ retry_upto(3, :interval => 5, :growth => 3){ @target.foo! }
54
64
  end
55
65
 
56
66
  def test_grow_for_inverval_between_attempts_can_be_defined_with_a_lambda
57
67
  self.expects(:sleep).times(1).with(5)
58
68
  self.expects(:sleep).times(1).with(7)
59
- retry_upto(3, :interval => 5, :growth => lambda{ |t| t + 2 }){ @target.hit! }
69
+ retry_upto(3, :interval => 5, :growth => lambda{ |t| t + 2 }){ @target.foo! }
60
70
  end
61
71
 
62
72
  # exceptions
63
73
 
64
74
  def test_by_default_any_exception_gets_captured_if_there_are_attempts_left
65
- retry_upto(3){ @target.hit! }
75
+ retry_upto(3){ @target.foo! }
66
76
  assert true # if we reach this no exception was raised out of retry_upto
67
77
  end
68
78
 
69
79
  def test_the_last_attempt_does_not_capture_the_exception
70
80
  assert_raises(FooError) do
71
- retry_upto(2){ @target.hit! }
81
+ retry_upto(2){ @target.foo! }
72
82
  end
73
83
  end
74
84
 
75
85
  def test_a_specified_exception_will_be_captured_between_attempts
76
- retry_upto(3, :rescue => FooError){ @target.hit! }
86
+ retry_upto(3, :rescue => FooError){ @target.foo! }
87
+ assert true # if we reach this no exception was raised out of retry_upto
88
+ end
89
+
90
+ def test_several_specified_exceptions_will_be_captured_between_attempts
91
+ retry_upto(3, :rescue => [FooError, BarError]){ @target.foo! }
92
+ retry_upto(3, :rescue => [FooError, BarError]){ @target.bar! }
77
93
  assert true # if we reach this no exception was raised out of retry_upto
78
94
  end
79
95
 
80
96
  def test_the_last_attempt_does_not_capture_the_specified_exception
81
97
  assert_raises(FooError) do
82
- retry_upto(2, :rescue => FooError){ @target.hit! }
98
+ retry_upto(2, :rescue => FooError){ @target.foo! }
83
99
  end
84
100
  end
85
101
 
86
102
  def test_a_exception_different_from_the_specified_one_will_not_be_captured_between_attempts
87
103
  assert_raises(FooError) do
88
- retry_upto(3, :rescue => ZeroDivisionError){ @target.hit! }
104
+ retry_upto(3, :rescue => ZeroDivisionError){ @target.foo! }
89
105
  end
90
106
  end
91
107
 
metadata CHANGED
@@ -1,84 +1,61 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: retry_upto
3
- version: !ruby/object:Gem::Version
4
- hash: 15
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.1'
5
5
  prerelease:
6
- segments:
7
- - 1
8
- - 0
9
- version: "1.0"
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Raul Murciano
13
9
  - Glenn Gillen
14
10
  - Pedro Belo
15
11
  - Jaime Iniesta
16
- - "Lle\xC3\xAFr Borras"
17
- - "Aitor Garc\xC3\xADa Rey"
12
+ - Lleïr Borras
13
+ - Aitor García Rey
18
14
  autorequire:
19
15
  bindir: bin
20
16
  cert_chain: []
21
-
22
- date: 2011-10-07 00:00:00 -07:00
23
- default_executable:
24
- dependencies:
25
- - !ruby/object:Gem::Dependency
17
+ date: 2011-10-08 00:00:00.000000000Z
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
26
20
  name: minitest
27
- prerelease: false
28
- requirement: &id001 !ruby/object:Gem::Requirement
21
+ requirement: &2153033700 !ruby/object:Gem::Requirement
29
22
  none: false
30
- requirements:
31
- - - ">"
32
- - !ruby/object:Gem::Version
33
- hash: 3
34
- segments:
35
- - 2
36
- - 0
37
- version: "2.0"
23
+ requirements:
24
+ - - ! '>'
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
38
27
  type: :development
39
- version_requirements: *id001
40
- - !ruby/object:Gem::Dependency
41
- name: mocha
42
28
  prerelease: false
43
- requirement: &id002 !ruby/object:Gem::Requirement
29
+ version_requirements: *2153033700
30
+ - !ruby/object:Gem::Dependency
31
+ name: mocha
32
+ requirement: &2153033220 !ruby/object:Gem::Requirement
44
33
  none: false
45
- requirements:
46
- - - ">="
47
- - !ruby/object:Gem::Version
48
- hash: 55
49
- segments:
50
- - 0
51
- - 10
52
- - 0
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
53
37
  version: 0.10.0
54
38
  type: :development
55
- version_requirements: *id002
56
- - !ruby/object:Gem::Dependency
57
- name: rake
58
39
  prerelease: false
59
- requirement: &id003 !ruby/object:Gem::Requirement
40
+ version_requirements: *2153033220
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: &2153032760 !ruby/object:Gem::Requirement
60
44
  none: false
61
- requirements:
62
- - - ">="
63
- - !ruby/object:Gem::Version
64
- hash: 63
65
- segments:
66
- - 0
67
- - 9
68
- - 2
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
69
48
  version: 0.9.2
70
49
  type: :development
71
- version_requirements: *id003
50
+ prerelease: false
51
+ version_requirements: *2153032760
72
52
  description: adds some useful options to retry code blocks
73
- email:
53
+ email:
74
54
  - raul@murciano.net
75
55
  executables: []
76
-
77
56
  extensions: []
78
-
79
57
  extra_rdoc_files: []
80
-
81
- files:
58
+ files:
82
59
  - lib/retry_upto.rb
83
60
  - test/retry_upto_test.rb
84
61
  - test/test_helper.rb
@@ -87,39 +64,28 @@ files:
87
64
  - LICENSE
88
65
  - RakeFile
89
66
  - README.md
90
- has_rdoc: true
91
67
  homepage: http://github.com/raul/retry_upto
92
68
  licenses: []
93
-
94
69
  post_install_message:
95
70
  rdoc_options: []
96
-
97
- require_paths:
71
+ require_paths:
98
72
  - lib
99
- required_ruby_version: !ruby/object:Gem::Requirement
73
+ required_ruby_version: !ruby/object:Gem::Requirement
100
74
  none: false
101
- requirements:
102
- - - ">="
103
- - !ruby/object:Gem::Version
104
- hash: 3
105
- segments:
106
- - 0
107
- version: "0"
108
- required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
80
  none: false
110
- requirements:
111
- - - ">="
112
- - !ruby/object:Gem::Version
113
- hash: 3
114
- segments:
115
- - 0
116
- version: "0"
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
117
85
  requirements: []
118
-
119
86
  rubyforge_project: retry_upto
120
- rubygems_version: 1.5.2
87
+ rubygems_version: 1.8.10
121
88
  signing_key:
122
89
  specification_version: 3
123
90
  summary: retry with steroids
124
91
  test_files: []
125
-