retryable 1.3.6 → 2.0.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 +4 -0
- data/README.md +10 -10
- data/lib/retryable.rb +4 -4
- data/lib/retryable/version.rb +3 -3
- data/spec/lib/config_spec.rb +4 -4
- data/spec/lib/retryable_spec.rb +44 -44
- data/spec/spec_helper.rb +2 -4
- metadata +13 -11
- checksums.yaml +0 -7
- data/spec/lib/version_spec.rb +0 -7
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -24,7 +24,7 @@ Open an URL, retry up to two times when an `OpenURI::HTTPError` occurs.
|
|
24
24
|
``` ruby
|
25
25
|
require "open-uri"
|
26
26
|
|
27
|
-
retryable(:tries => 3, :on => OpenURI::HTTPError) do
|
27
|
+
Retryable.retryable(:tries => 3, :on => OpenURI::HTTPError) do
|
28
28
|
xml = open("http://example.com/test.xml").read
|
29
29
|
end
|
30
30
|
```
|
@@ -33,7 +33,7 @@ Do _something_, retry up to four times for either `ArgumentError` or
|
|
33
33
|
`TimeoutError` exceptions.
|
34
34
|
|
35
35
|
``` ruby
|
36
|
-
retryable(:tries => 5, :on => [ArgumentError, TimeoutError]) do
|
36
|
+
Retryable.retryable(:tries => 5, :on => [ArgumentError, TimeoutError]) do
|
37
37
|
# some crazy code
|
38
38
|
end
|
39
39
|
```
|
@@ -49,7 +49,7 @@ ensure_cb = Proc.new do |retries|
|
|
49
49
|
f.close
|
50
50
|
end
|
51
51
|
|
52
|
-
retryable(:ensure => ensure_cb) do
|
52
|
+
Retryable.retryable(:ensure => ensure_cb) do
|
53
53
|
# process file
|
54
54
|
end
|
55
55
|
```
|
@@ -63,9 +63,9 @@ Sleeping
|
|
63
63
|
By default Retryable waits for one second between retries. You can change this and even provide your own exponential backoff scheme.
|
64
64
|
|
65
65
|
```
|
66
|
-
retryable(:sleep => 0) { }
|
67
|
-
retryable(:sleep => 10) { }
|
68
|
-
retryable(:sleep => lambda { |n| 4**n }) { } # sleep 1, 4, 16, etc. each try
|
66
|
+
Retryable.retryable(:sleep => 0) { } # don't pause at all between retries
|
67
|
+
Retryable.retryable(:sleep => 10) { } # sleep ten seconds between retries
|
68
|
+
Retryable.retryable(:sleep => lambda { |n| 4**n }) { } # sleep 1, 4, 16, etc. each try
|
69
69
|
```
|
70
70
|
|
71
71
|
Matching error messages
|
@@ -73,7 +73,7 @@ Matching error messages
|
|
73
73
|
You can also retry based on the exception message:
|
74
74
|
|
75
75
|
```
|
76
|
-
retryable(:matching => /IO timeout/) do |retries, exception|
|
76
|
+
Retryable.retryable(:matching => /IO timeout/) do |retries, exception|
|
77
77
|
raise "yo, IO timeout!" if retries == 0
|
78
78
|
end
|
79
79
|
```
|
@@ -83,7 +83,7 @@ Block Parameters
|
|
83
83
|
Your block is called with two optional parameters: the number of tries until now, and the most recent exception.
|
84
84
|
|
85
85
|
```
|
86
|
-
retryable do |retries, exception|
|
86
|
+
Retryable.retryable do |retries, exception|
|
87
87
|
puts "try #{retries} failed with exception: #{exception}" if retries > 0
|
88
88
|
pick_up_soap
|
89
89
|
end
|
@@ -98,7 +98,7 @@ exception_cb = Proc.new do |exception|
|
|
98
98
|
ExceptionNotifier.notify_exception(exception, :data => {:message => "it failed"})
|
99
99
|
end
|
100
100
|
|
101
|
-
retryable(:exception_cb => exception_cb) do
|
101
|
+
Retryable.retryable(:exception_cb => exception_cb) do
|
102
102
|
# perform risky operation
|
103
103
|
end
|
104
104
|
```
|
@@ -126,7 +126,7 @@ versions:
|
|
126
126
|
* Ruby 1.9.2
|
127
127
|
* Ruby 1.9.3
|
128
128
|
* Ruby 2.0.0
|
129
|
-
* Ruby 2.1.
|
129
|
+
* Ruby 2.1.2
|
130
130
|
|
131
131
|
If something doesn't work on one of these versions, it's a bug.
|
132
132
|
|
data/lib/retryable.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'retryable/version'
|
2
2
|
require 'retryable/config'
|
3
3
|
|
4
|
-
module
|
5
|
-
def retryable(options = {}, &block)
|
4
|
+
module Retryable
|
5
|
+
def self.retryable(options = {}, &block)
|
6
6
|
opts = {:tries => 2, :sleep => 1, :on => StandardError, :matching => /.*/, :ensure => Proc.new {}, :exception_cb => Proc.new {}}
|
7
7
|
check_for_invalid_options(options, opts)
|
8
8
|
opts.merge!(options)
|
@@ -22,7 +22,7 @@ module Kernel
|
|
22
22
|
|
23
23
|
# Interrupt Exception could be raised while sleeping
|
24
24
|
begin
|
25
|
-
sleep opts[:sleep].respond_to?(:call) ? opts[:sleep].call(retries) : opts[:sleep]
|
25
|
+
Kernel.sleep opts[:sleep].respond_to?(:call) ? opts[:sleep].call(retries) : opts[:sleep]
|
26
26
|
rescue *on_exception
|
27
27
|
end
|
28
28
|
|
@@ -37,7 +37,7 @@ module Kernel
|
|
37
37
|
|
38
38
|
private
|
39
39
|
|
40
|
-
def check_for_invalid_options(custom_options, default_options)
|
40
|
+
def self.check_for_invalid_options(custom_options, default_options)
|
41
41
|
invalid_options = default_options.merge(custom_options).keys - default_options.keys
|
42
42
|
|
43
43
|
raise ArgumentError.new("[Retryable] Invalid options: #{invalid_options.join(", ")}") unless invalid_options.empty?
|
data/lib/retryable/version.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Retryable
|
2
2
|
class Version
|
3
|
-
MAJOR =
|
4
|
-
MINOR =
|
5
|
-
PATCH =
|
3
|
+
MAJOR = 2 unless defined? Retryable::Version::MAJOR
|
4
|
+
MINOR = 0 unless defined? Retryable::Version::MINOR
|
5
|
+
PATCH = 0 unless defined? Retryable::Version::PATCH
|
6
6
|
|
7
7
|
class << self
|
8
8
|
|
data/spec/lib/config_spec.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Retryable do
|
3
|
+
RSpec.describe Retryable do
|
4
4
|
it 'is enabled by default' do
|
5
|
-
Retryable.
|
5
|
+
expect(Retryable).to be_enabled
|
6
6
|
end
|
7
7
|
|
8
8
|
it 'could be disabled' do
|
9
9
|
Retryable.disable
|
10
|
-
Retryable.
|
10
|
+
expect(Retryable).not_to be_enabled
|
11
11
|
end
|
12
12
|
|
13
13
|
context 'when disabled' do
|
@@ -17,7 +17,7 @@ describe Retryable do
|
|
17
17
|
|
18
18
|
it 'could be re-enabled' do
|
19
19
|
Retryable.enable
|
20
|
-
Retryable.
|
20
|
+
expect(Retryable).to be_enabled
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
data/spec/lib/retryable_spec.rb
CHANGED
@@ -1,118 +1,118 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe '
|
3
|
+
RSpec.describe 'Retryable.retryable' do
|
4
4
|
before(:each) do
|
5
5
|
Retryable.enable
|
6
6
|
@attempt = 0
|
7
7
|
end
|
8
8
|
|
9
9
|
it 'catch StandardError only by default' do
|
10
|
-
|
10
|
+
expect do
|
11
11
|
count_retryable(:tries => 2) { |tries, ex| raise Exception if tries < 1 }
|
12
|
-
end.
|
13
|
-
@try_count.
|
12
|
+
end.to raise_error Exception
|
13
|
+
expect(@try_count).to eq(1)
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'retries on default exception' do
|
17
|
-
Kernel.
|
17
|
+
expect(Kernel).to receive(:sleep).once.with(1)
|
18
18
|
|
19
19
|
count_retryable(:tries => 2) { |tries, ex| raise StandardError if tries < 1 }
|
20
|
-
@try_count.
|
20
|
+
expect(@try_count).to eq(2)
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'does not retry if disabled' do
|
24
24
|
Retryable.disable
|
25
25
|
|
26
|
-
|
26
|
+
expect do
|
27
27
|
count_retryable(:tries => 2) { raise }
|
28
|
-
end.
|
29
|
-
@try_count.
|
28
|
+
end.to raise_error RuntimeError
|
29
|
+
expect(@try_count).to eq(1)
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'executes *ensure* clause' do
|
33
33
|
ensure_cb = Proc.new do |retries|
|
34
|
-
retries.
|
34
|
+
expect(retries).to eq(0)
|
35
35
|
end
|
36
36
|
|
37
|
-
|
37
|
+
Retryable.retryable(:ensure => ensure_cb) { }
|
38
38
|
end
|
39
39
|
|
40
40
|
it 'passes retry count and exception on retry' do
|
41
|
-
Kernel.
|
41
|
+
expect(Kernel).to receive(:sleep).once.with(1)
|
42
42
|
|
43
43
|
count_retryable(:tries => 2) do |tries, ex|
|
44
|
-
ex.class.
|
44
|
+
expect(ex.class).to eq(StandardError) if tries > 0
|
45
45
|
raise StandardError if tries < 1
|
46
46
|
end
|
47
|
-
@try_count.
|
47
|
+
expect(@try_count).to eq(2)
|
48
48
|
end
|
49
49
|
|
50
50
|
it 'makes another try if exception is covered by :on' do
|
51
|
-
Kernel.
|
51
|
+
allow(Kernel).to receive(:sleep)
|
52
52
|
count_retryable(:on => [StandardError, ArgumentError, RuntimeError] ) { |tries, ex| raise ArgumentError if tries < 1 }
|
53
|
-
@try_count.
|
53
|
+
expect(@try_count).to eq(2)
|
54
54
|
end
|
55
55
|
|
56
56
|
it 'does not try on unexpected exception' do
|
57
|
-
Kernel.
|
58
|
-
|
57
|
+
allow(Kernel).to receive(:sleep)
|
58
|
+
expect do
|
59
59
|
count_retryable(:on => RuntimeError ) { |tries, ex| raise StandardError if tries < 1 }
|
60
|
-
end.
|
61
|
-
@try_count.
|
60
|
+
end.to raise_error StandardError
|
61
|
+
expect(@try_count).to eq(1)
|
62
62
|
end
|
63
63
|
|
64
64
|
it 'retries three times' do
|
65
|
-
Kernel.
|
65
|
+
allow(Kernel).to receive(:sleep)
|
66
66
|
count_retryable(:tries => 3) { |tries, ex| raise StandardError if tries < 2 }
|
67
|
-
@try_count.
|
67
|
+
expect(@try_count).to eq(3)
|
68
68
|
end
|
69
69
|
|
70
70
|
it 'retries on default exception' do
|
71
|
-
Kernel.
|
71
|
+
expect(Kernel).to receive(:sleep).once.with(1)
|
72
72
|
|
73
73
|
count_retryable(:tries => 2) { |tries, ex| raise StandardError if tries < 1 }
|
74
|
-
@try_count.
|
74
|
+
expect(@try_count).to eq(2)
|
75
75
|
end
|
76
76
|
|
77
77
|
it 'executes exponential backoff scheme for :sleep option' do
|
78
|
-
[1, 4, 16, 64].each { |i| Kernel.
|
79
|
-
|
80
|
-
|
81
|
-
end.
|
78
|
+
[1, 4, 16, 64].each { |i| expect(Kernel).to receive(:sleep).once.ordered.with(i) }
|
79
|
+
expect do
|
80
|
+
Retryable.retryable(:tries => 5, :sleep => lambda { |n| 4**n }) { raise RangeError }
|
81
|
+
end.to raise_error RangeError
|
82
82
|
end
|
83
83
|
|
84
84
|
it 'does not retry any exception if :on is empty list' do
|
85
|
-
|
85
|
+
expect do
|
86
86
|
count_retryable(:on => []) { raise }
|
87
|
-
end.
|
88
|
-
@try_count.
|
87
|
+
end.to raise_error RuntimeError
|
88
|
+
expect(@try_count).to eq(1)
|
89
89
|
end
|
90
90
|
|
91
91
|
it 'catches an exception that matches the regex' do
|
92
|
-
Kernel.
|
92
|
+
expect(Kernel).to receive(:sleep).once.with(1)
|
93
93
|
count_retryable(:matching => /IO timeout/) { |c,e| raise "yo, IO timeout!" if c == 0 }
|
94
|
-
@try_count.
|
94
|
+
expect(@try_count).to eq(2)
|
95
95
|
end
|
96
96
|
|
97
97
|
it 'does not catch an exception that does not match the regex' do
|
98
|
-
|
99
|
-
|
98
|
+
expect(Kernel).not_to receive(:sleep)
|
99
|
+
expect do
|
100
100
|
count_retryable(:matching => /TimeError/) { raise "yo, IO timeout!" }
|
101
|
-
end.
|
102
|
-
@try_count.
|
101
|
+
end.to raise_error RuntimeError
|
102
|
+
expect(@try_count).to eq(1)
|
103
103
|
end
|
104
104
|
|
105
105
|
it 'does not allow invalid options' do
|
106
|
-
|
107
|
-
retryable(:bad_option => 2) { raise "this is bad" }
|
108
|
-
end.
|
106
|
+
expect do
|
107
|
+
Retryable.retryable(:bad_option => 2) { raise "this is bad" }
|
108
|
+
end.to raise_error ArgumentError, '[Retryable] Invalid options: bad_option'
|
109
109
|
end
|
110
110
|
|
111
111
|
it 'accepts a callback to run after an exception is rescued' do
|
112
|
-
|
113
|
-
retryable(:sleep => 0, :exception_cb => Proc.new {|e| @raised = e.to_s }) {|tries, ex| raise StandardError.new("this is fun!") if tries < 1 }
|
114
|
-
end.
|
112
|
+
expect do
|
113
|
+
Retryable.retryable(:sleep => 0, :exception_cb => Proc.new {|e| @raised = e.to_s }) {|tries, ex| raise StandardError.new("this is fun!") if tries < 1 }
|
114
|
+
end.not_to raise_error
|
115
115
|
|
116
|
-
@raised.
|
116
|
+
expect(@raised).to eq("this is fun!")
|
117
117
|
end
|
118
118
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,13 +2,11 @@ require File.dirname(__FILE__) + '/../lib/retryable'
|
|
2
2
|
require 'rspec'
|
3
3
|
|
4
4
|
RSpec.configure do |config|
|
5
|
-
|
6
|
-
# methods or matchers
|
7
|
-
require 'rspec/expectations'
|
5
|
+
config.disable_monkey_patching!
|
8
6
|
|
9
7
|
def count_retryable(*opts)
|
10
8
|
@try_count = 0
|
11
|
-
return
|
9
|
+
return Retryable.retryable(*opts) do |*args|
|
12
10
|
@try_count += 1
|
13
11
|
yield *args
|
14
12
|
end
|
metadata
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: retryable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Nikita Fedyashev
|
@@ -10,11 +11,12 @@ authors:
|
|
10
11
|
autorequire:
|
11
12
|
bindir: bin
|
12
13
|
cert_chain: []
|
13
|
-
date: 2014-
|
14
|
+
date: 2014-12-03 00:00:00.000000000 Z
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|
16
17
|
name: bundler
|
17
18
|
requirement: !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
18
20
|
requirements:
|
19
21
|
- - ~>
|
20
22
|
- !ruby/object:Gem::Version
|
@@ -22,6 +24,7 @@ dependencies:
|
|
22
24
|
type: :development
|
23
25
|
prerelease: false
|
24
26
|
version_requirements: !ruby/object:Gem::Requirement
|
27
|
+
none: false
|
25
28
|
requirements:
|
26
29
|
- - ~>
|
27
30
|
- !ruby/object:Gem::Version
|
@@ -36,40 +39,39 @@ files:
|
|
36
39
|
- LICENSE.md
|
37
40
|
- README.md
|
38
41
|
- Rakefile
|
39
|
-
-
|
42
|
+
- retryable.gemspec
|
40
43
|
- lib/retryable/config.rb
|
41
44
|
- lib/retryable/version.rb
|
42
|
-
- retryable.
|
45
|
+
- lib/retryable.rb
|
43
46
|
- spec/lib/config_spec.rb
|
44
47
|
- spec/lib/retryable_spec.rb
|
45
|
-
- spec/lib/version_spec.rb
|
46
48
|
- spec/spec_helper.rb
|
47
49
|
homepage: http://github.com/nfedyashev/retryable
|
48
50
|
licenses: []
|
49
|
-
metadata: {}
|
50
51
|
post_install_message:
|
51
52
|
rdoc_options: []
|
52
53
|
require_paths:
|
53
54
|
- lib
|
54
55
|
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
55
57
|
requirements:
|
56
|
-
- - '>='
|
58
|
+
- - ! '>='
|
57
59
|
- !ruby/object:Gem::Version
|
58
60
|
version: '0'
|
59
61
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
60
63
|
requirements:
|
61
|
-
- - '>='
|
64
|
+
- - ! '>='
|
62
65
|
- !ruby/object:Gem::Version
|
63
66
|
version: 1.3.6
|
64
67
|
requirements: []
|
65
68
|
rubyforge_project:
|
66
|
-
rubygems_version:
|
69
|
+
rubygems_version: 1.8.23
|
67
70
|
signing_key:
|
68
|
-
specification_version:
|
71
|
+
specification_version: 3
|
69
72
|
summary: Kernel#retryable, allow for retrying of code blocks.
|
70
73
|
test_files:
|
71
74
|
- spec/lib/config_spec.rb
|
72
75
|
- spec/lib/retryable_spec.rb
|
73
|
-
- spec/lib/version_spec.rb
|
74
76
|
- spec/spec_helper.rb
|
75
77
|
has_rdoc:
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: c055a594c5bd9ebeb455b8185e027ea0d2ce259c
|
4
|
-
data.tar.gz: 2cbbb09e5958d1f211810dbc762bfd962a102eaf
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: c1f320b8298024f48f24677e4538d6da832287a7f00269da165b41454a242e2777bc7978c84916148afaa50bf63936090ae315da8e151b9fe3d6ae60d7085229
|
7
|
-
data.tar.gz: f75b5c6bc559c0b5841a95d74914ac16fe24e399365aed35a3b9c7500c1c08d9a636def180e12f0773558252f1ddc371fcf5496f47e16301f300e00ebef904f2
|