retry_upto 1.0

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.
data/Changelog.md ADDED
@@ -0,0 +1,5 @@
1
+ # retry_upto changelog
2
+
3
+ ## v1.0
4
+
5
+ First version
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2011 Raul Murciano, Glenn Gillen, Pedro Belo,
2
+ Jaime Iniesta, Lleïr Borras and Aitor García Rey.
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # retry_upto: retry with steroids
2
+
3
+ ## Usage
4
+
5
+ Basic usage
6
+
7
+ - retries up to 5 times catching any exception, doesn't wait between attempts:
8
+
9
+ retry_upto(5) do ... end
10
+
11
+ Waiting time between attempts
12
+
13
+ - retries up to 5 times, waits 2 seconds between attempts:
14
+
15
+ retry_upto(5, :interval => 2) do ... end
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
+ Retrying only when certain Exceptions get raised
35
+
36
+ - retries up to 5 times only after a ZeroDivisionError, raising any other Exception:
37
+
38
+ retry_upto(5, :rescue => ZeroDivisionError) do ... end
39
+
40
+ All the options described above can be combined together.
41
+
42
+ ## License
43
+
44
+ See the LICENSE file included in the distribution.
45
+
46
+ ## Authors
47
+
48
+ This gem was born from gists by Raul Murciano, Glenn Gillen, Pedro Belo, Jaime Iniesta, Lleïr Borras and ideas taken from Aitor García Rey.
49
+
50
+ Yes, so many brain cells and so few lines of code. Great, isn't it?
51
+
data/RakeFile ADDED
@@ -0,0 +1,11 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ task :default => [:test]
5
+
6
+ desc 'Run tests'
7
+ Rake::TestTask.new('test') do |t|
8
+ t.pattern = 'test/*_test.rb'
9
+ t.verbose = true
10
+ t.warning = true
11
+ end
data/lib/retry_upto.rb ADDED
@@ -0,0 +1,70 @@
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.
43
+
44
+ def retry_upto(max_retries = 1, options = {})
45
+ yield
46
+ rescue (options[:rescue] || Exception)
47
+ raise if (max_retries -= 1) == 0
48
+ sleep(options[:interval] || 0)
49
+ if options[:growth].respond_to?('*')
50
+ options[:interval] = options[:interval] * options[:growth]
51
+ elsif options[:growth].respond_to?(:call)
52
+ options[:interval] = options[:growth].call(options[:interval])
53
+ end
54
+ retry
55
+ end
56
+
57
+
58
+
59
+ # Extends enumerator to allow usage like:
60
+ #
61
+ # 5.times.retry do
62
+ # ...
63
+ # end
64
+ #
65
+
66
+ class Enumerator
67
+ def retry(options = {}, &blk)
68
+ retry_upto(self.count, options, &blk)
69
+ end
70
+ end
@@ -0,0 +1,92 @@
1
+ require './test/test_helper'
2
+
3
+ class Retry_uptoTest < MiniTest::Unit::TestCase
4
+
5
+ class FooError < Exception; end
6
+
7
+ # raises ZeroDivisionError in the two first hits
8
+ class Target
9
+ attr_accessor :hits
10
+ def initialize; @hits = 0; end
11
+
12
+ def hit!
13
+ @hits += 1
14
+ raise FooError if @hits < 3
15
+ end
16
+ end
17
+
18
+ def setup
19
+ @target = Target.new
20
+ end
21
+
22
+ # number of attempts
23
+
24
+ def test_retries_one_time_by_default_without_capturing_the_exception
25
+ assert_raises(FooError) do
26
+ retry_upto{ @target.hit! }
27
+ end
28
+ assert_equal 1, @target.hits
29
+ end
30
+
31
+ def test_retries_the_desired_number_of_attempts
32
+ retry_upto(3){ @target.hit! }
33
+ assert_equal 3, @target.hits
34
+ end
35
+
36
+ # interval between attempts
37
+
38
+ def test_there_is_no_interval_between_attempts_by_default
39
+ self.expects(:sleep).times(2).with(0).returns(nil)
40
+ retry_upto(3){ @target.hit! }
41
+ end
42
+
43
+ def test_interval_between_attempts_can_be_customized
44
+ self.expects(:sleep).times(2).with(5).returns(nil)
45
+ retry_upto(3, :interval => 5){ @target.hit! }
46
+ end
47
+
48
+ # interval growth between attempts
49
+
50
+ def test_inverval_can_be_multiplied_by_an_integer_growth
51
+ self.expects(:sleep).times(1).with(5)
52
+ self.expects(:sleep).times(1).with(15)
53
+ retry_upto(3, :interval => 5, :growth => 3){ @target.hit! }
54
+ end
55
+
56
+ def test_grow_for_inverval_between_attempts_can_be_defined_with_a_lambda
57
+ self.expects(:sleep).times(1).with(5)
58
+ self.expects(:sleep).times(1).with(7)
59
+ retry_upto(3, :interval => 5, :growth => lambda{ |t| t + 2 }){ @target.hit! }
60
+ end
61
+
62
+ # exceptions
63
+
64
+ def test_by_default_any_exception_gets_captured_if_there_are_attempts_left
65
+ retry_upto(3){ @target.hit! }
66
+ assert true # if we reach this no exception was raised out of retry_upto
67
+ end
68
+
69
+ def test_the_last_attempt_does_not_capture_the_exception
70
+ assert_raises(FooError) do
71
+ retry_upto(2){ @target.hit! }
72
+ end
73
+ end
74
+
75
+ def test_a_specified_exception_will_be_captured_between_attempts
76
+ retry_upto(3, :rescue => FooError){ @target.hit! }
77
+ assert true # if we reach this no exception was raised out of retry_upto
78
+ end
79
+
80
+ def test_the_last_attempt_does_not_capture_the_specified_exception
81
+ assert_raises(FooError) do
82
+ retry_upto(2, :rescue => FooError){ @target.hit! }
83
+ end
84
+ end
85
+
86
+ def test_a_exception_different_from_the_specified_one_will_not_be_captured_between_attempts
87
+ assert_raises(FooError) do
88
+ retry_upto(3, :rescue => ZeroDivisionError){ @target.hit! }
89
+ end
90
+ end
91
+
92
+ end
@@ -0,0 +1,4 @@
1
+ require 'rubygems'
2
+ require 'minitest/autorun'
3
+ require 'mocha'
4
+ require './lib/retry_upto'
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: retry_upto
3
+ version: !ruby/object:Gem::Version
4
+ hash: 15
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ version: "1.0"
10
+ platform: ruby
11
+ authors:
12
+ - Raul Murciano
13
+ - Glenn Gillen
14
+ - Pedro Belo
15
+ - Jaime Iniesta
16
+ - "Lle\xC3\xAFr Borras"
17
+ - "Aitor Garc\xC3\xADa Rey"
18
+ autorequire:
19
+ bindir: bin
20
+ cert_chain: []
21
+
22
+ date: 2011-10-07 00:00:00 -07:00
23
+ default_executable:
24
+ dependencies:
25
+ - !ruby/object:Gem::Dependency
26
+ name: minitest
27
+ prerelease: false
28
+ requirement: &id001 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ">"
32
+ - !ruby/object:Gem::Version
33
+ hash: 3
34
+ segments:
35
+ - 2
36
+ - 0
37
+ version: "2.0"
38
+ type: :development
39
+ version_requirements: *id001
40
+ - !ruby/object:Gem::Dependency
41
+ name: mocha
42
+ prerelease: false
43
+ requirement: &id002 !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ hash: 55
49
+ segments:
50
+ - 0
51
+ - 10
52
+ - 0
53
+ version: 0.10.0
54
+ type: :development
55
+ version_requirements: *id002
56
+ - !ruby/object:Gem::Dependency
57
+ name: rake
58
+ prerelease: false
59
+ requirement: &id003 !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ hash: 63
65
+ segments:
66
+ - 0
67
+ - 9
68
+ - 2
69
+ version: 0.9.2
70
+ type: :development
71
+ version_requirements: *id003
72
+ description: adds some useful options to retry code blocks
73
+ email:
74
+ - raul@murciano.net
75
+ executables: []
76
+
77
+ extensions: []
78
+
79
+ extra_rdoc_files: []
80
+
81
+ files:
82
+ - lib/retry_upto.rb
83
+ - test/retry_upto_test.rb
84
+ - test/test_helper.rb
85
+ - Changelog.md
86
+ - Gemfile
87
+ - LICENSE
88
+ - RakeFile
89
+ - README.md
90
+ has_rdoc: true
91
+ homepage: http://github.com/raul/retry_upto
92
+ licenses: []
93
+
94
+ post_install_message:
95
+ rdoc_options: []
96
+
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ 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
109
+ none: false
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ hash: 3
114
+ segments:
115
+ - 0
116
+ version: "0"
117
+ requirements: []
118
+
119
+ rubyforge_project: retry_upto
120
+ rubygems_version: 1.5.2
121
+ signing_key:
122
+ specification_version: 3
123
+ summary: retry with steroids
124
+ test_files: []
125
+