tries 0.2.1 → 0.3.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.
- checksums.yaml +6 -14
- data/LICENSE.txt +1 -1
- data/README.md +87 -11
- data/lib/tries.rb +14 -2
- data/lib/tries/version.rb +1 -1
- data/spec/tries/tries_spec.rb +69 -13
- data/tries.gemspec +3 -2
- metadata +32 -30
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
metadata.gz: !binary |-
|
9
|
-
NmJlZWY0MzJmNmU0ZjkyOWM5OWUyMjcyODJhMDA0NjRhN2RkOTUxZmZiZGYw
|
10
|
-
OGViYTYxZGFmMjBiN2M2NmM5ZDRlNmNjMDRiMzY5YTFjYjllODlmNTM4ZTc0
|
11
|
-
NTUzMjMxMWJkYTJiNjczYjVkNjc3YjM0OWIyNWQ4NjBlMDAxNDk=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
NzMyNmQ1YTc1NTFjOTRlZWJiZGE0ZGQyN2U5ZDI4MjE2YTQzNDgxZjJhNWZi
|
14
|
-
NzVlZDM1NzVlODVlMThmYTAwYmIwM2U2ZmFlNWM4YjZjNmEyOGFhMWRmOTBh
|
15
|
-
YTc2M2YyMjdhOTNkMWFjNGMyMmZiODJjNTlhMGFjZDMzNGFmMGM=
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 858991b157959d16b2013139b86b0177bf8fa8f7
|
4
|
+
data.tar.gz: 78375500627b00b518e892279a631421287fb2fb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2c0552f9fb62b8bbf2ab74221ed5b89d67a27dc35ca88a7907849ce244a1c734a2f1ecd0c6fada7cf1a99e15be01a52e0403820dc919cc43e89df6cfd27577c1
|
7
|
+
data.tar.gz: 8fd511848722e6f26db4ffa07ad06cbf8cd556f83ab47ebcf5e7f62f5def8b2ae0cb0a6e3aaf3430d35ebbd9ff4e4df29937ef56ad0a4ab2983e67486764e5a8
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# Tries
|
2
2
|
|
3
|
+
[](http://badge.fury.io/rb/tries)
|
3
4
|
[](http://travis-ci.org/krautcomputing/tries)
|
4
5
|
[](https://gemnasium.com/krautcomputing/tries)
|
5
|
-
[](https://codeclimate.com/github/krautcomputing/tries)
|
6
7
|
|
7
8
|
Solidify your code and retry on petty exceptions.
|
8
9
|
|
@@ -40,9 +41,9 @@ end
|
|
40
41
|
|
41
42
|
## Detailed usage
|
42
43
|
|
43
|
-
|
44
|
-
# Helper code to explain how it works
|
44
|
+
### Helper code to explain how it works
|
45
45
|
|
46
|
+
```ruby
|
46
47
|
FooError = Class.new(StandardError)
|
47
48
|
BarError = Class.new(StandardError)
|
48
49
|
|
@@ -63,8 +64,9 @@ def method_that_raises_exception
|
|
63
64
|
end
|
64
65
|
```
|
65
66
|
|
67
|
+
### Rescue all errors
|
68
|
+
|
66
69
|
```ruby
|
67
|
-
# Rescue all errors
|
68
70
|
4.tries do
|
69
71
|
method_that_raises_exception
|
70
72
|
end
|
@@ -77,8 +79,9 @@ end
|
|
77
79
|
=> You made it through!
|
78
80
|
```
|
79
81
|
|
82
|
+
### Rescue a specific error
|
83
|
+
|
80
84
|
```ruby
|
81
|
-
# Rescue a specific error
|
82
85
|
3.tries on: FooError do
|
83
86
|
method_that_raises_exception
|
84
87
|
end
|
@@ -86,11 +89,12 @@ end
|
|
86
89
|
=> Counter is 1
|
87
90
|
=> Counter is 2
|
88
91
|
=> Counter is 3
|
89
|
-
=> BarError
|
92
|
+
=> BarError
|
90
93
|
```
|
91
94
|
|
95
|
+
### Rescue multiple errors
|
96
|
+
|
92
97
|
```ruby
|
93
|
-
# Rescue multiple errors
|
94
98
|
3.tries on: [FooError, BarError] do
|
95
99
|
method_that_raises_exception
|
96
100
|
end
|
@@ -99,12 +103,16 @@ end
|
|
99
103
|
=> Counter is 2
|
100
104
|
=> Counter is 3
|
101
105
|
=> Counter is 4
|
102
|
-
=> StandardError
|
106
|
+
=> StandardError
|
103
107
|
```
|
104
108
|
|
109
|
+
### Delay execution after error
|
110
|
+
|
111
|
+
`delay` is in seconds, fractions are possible
|
112
|
+
|
113
|
+
#### Static delay
|
114
|
+
|
105
115
|
```ruby
|
106
|
-
# Delay execution after error
|
107
|
-
# "delay" parameter is in seconds, fractions are possible
|
108
116
|
4.tries delay: 1.5 do
|
109
117
|
method_that_raises_exception
|
110
118
|
end
|
@@ -119,8 +127,11 @@ waits 1.5 seconds...
|
|
119
127
|
waits 1.5 seconds...
|
120
128
|
=> Counter is 5
|
121
129
|
=> You made it through!
|
130
|
+
```
|
122
131
|
|
123
|
-
|
132
|
+
#### Incremental delay
|
133
|
+
|
134
|
+
```ruby
|
124
135
|
4.tries delay: 1.5, incremental: true do
|
125
136
|
method_that_raises_exception
|
126
137
|
end
|
@@ -137,6 +148,71 @@ waits 6 seconds...
|
|
137
148
|
=> You made it through!
|
138
149
|
```
|
139
150
|
|
151
|
+
### Callback on error
|
152
|
+
|
153
|
+
You can set a method or Proc to be called every time an exception occurs. Either set it globally in an initializer, e.g. to log all exceptions to a service like [Airbrake](https://airbrake.io/), or locally when calling `tries`. If both a global callback and a local callback are set, both are called, the global one first.
|
154
|
+
|
155
|
+
#### Global callback
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
# config/initializers/tries.rb
|
159
|
+
Tries.configure do |config|
|
160
|
+
config.on_error = lambda do |exception, attempts, next_delay|
|
161
|
+
puts "Whow, a #{exception.class} just occurred! It was attempt nr. #{attempts} to do whatever I was doing."
|
162
|
+
if next_delay
|
163
|
+
puts "I'm gonna wait #{next_delay} seconds and try again."
|
164
|
+
else
|
165
|
+
puts "A delay was not configured so I'm gonna go for it again immediately."
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
```
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
3.tries delay: 0.5, incremental: true do
|
173
|
+
method_that_raises_exception
|
174
|
+
end
|
175
|
+
|
176
|
+
=> Counter is 1
|
177
|
+
=> Whow, a FooError just occurred! It was attempt nr. 1 to do whatever I was doing.
|
178
|
+
=> I'm gonna wait 0.5 seconds and try again.
|
179
|
+
waits 0.5 seconds...
|
180
|
+
=> Counter is 2
|
181
|
+
=> Whow, a FooError just occurred! It was attempt nr. 2 to do whatever I was doing.
|
182
|
+
=> I'm gonna wait 1.0 seconds and try again.
|
183
|
+
waits 1 second...
|
184
|
+
=> Counter is 3
|
185
|
+
=> Whow, a BarError just occurred! It was attempt nr. 3 to do whatever I was doing.
|
186
|
+
=> I'm gonna wait 1.5 seconds and try again.
|
187
|
+
waits 1.5 seconds...
|
188
|
+
=> Counter is 4
|
189
|
+
=> StandardError
|
190
|
+
```
|
191
|
+
|
192
|
+
#### Local callback
|
193
|
+
|
194
|
+
```ruby
|
195
|
+
callback = lambda do |exception, attempts, next_delay|
|
196
|
+
puts "Local callback! Exception: #{exception.class}, attempt: #{attempts}, next_delay: #{next_delay}"
|
197
|
+
end
|
198
|
+
|
199
|
+
3.tries delay: 0.5, incremental: true, on_error: callback do
|
200
|
+
method_that_raises_exception
|
201
|
+
end
|
202
|
+
|
203
|
+
=> Counter is 1
|
204
|
+
=> Local callback! Exception: FooError, attempt: 1, next_delay: 0.5
|
205
|
+
waits 0.5 seconds...
|
206
|
+
=> Counter is 2
|
207
|
+
=> Local callback! Exception: FooError, attempt: 2, next_delay: 1.0
|
208
|
+
waits 1 second...
|
209
|
+
=> Counter is 3
|
210
|
+
=> Local callback! Exception: BarError, attempt: 3, next_delay: 1.5
|
211
|
+
waits 1.5 seconds...
|
212
|
+
=> Counter is 4
|
213
|
+
=> StandardError
|
214
|
+
```
|
215
|
+
|
140
216
|
## Contributing
|
141
217
|
|
142
218
|
1. Fork it
|
data/lib/tries.rb
CHANGED
@@ -1,4 +1,13 @@
|
|
1
1
|
require 'tries/version'
|
2
|
+
require 'gem_config'
|
3
|
+
|
4
|
+
module Tries
|
5
|
+
include GemConfig::Base
|
6
|
+
|
7
|
+
with_configuration do
|
8
|
+
has :on_error, classes: Proc
|
9
|
+
end
|
10
|
+
end
|
2
11
|
|
3
12
|
class Integer
|
4
13
|
def tries(options = {}, &block)
|
@@ -9,8 +18,11 @@ class Integer
|
|
9
18
|
|
10
19
|
begin
|
11
20
|
return yield
|
12
|
-
rescue *exception_classes
|
13
|
-
|
21
|
+
rescue *exception_classes => exception
|
22
|
+
next_delay = calculate_delay(delay, attempts, incremental) if delay
|
23
|
+
Tries.configuration.on_error.call(exception, attempts, next_delay) if Tries.configuration.on_error
|
24
|
+
options[:on_error].call(exception, attempts, next_delay) if options[:on_error]
|
25
|
+
Kernel.sleep next_delay if delay
|
14
26
|
retry if (attempts += 1) <= self
|
15
27
|
end
|
16
28
|
|
data/lib/tries/version.rb
CHANGED
data/spec/tries/tries_spec.rb
CHANGED
@@ -60,26 +60,26 @@ describe Tries do
|
|
60
60
|
end
|
61
61
|
|
62
62
|
context 'when specifying a delay' do
|
63
|
-
let(:delay) {
|
63
|
+
let(:delay) { 0.1 }
|
64
64
|
|
65
|
-
|
66
|
-
|
65
|
+
context 'static delay' do
|
66
|
+
it 'sleeps the specified delay' do
|
67
|
+
Kernel.should_receive(:sleep).with(0.1).exactly(2).times
|
67
68
|
|
68
|
-
|
69
|
-
|
70
|
-
|
69
|
+
begin
|
70
|
+
3.tries on: FooError, delay: delay do
|
71
|
+
raise_foo_foo_bar_bar_standard
|
72
|
+
end
|
73
|
+
rescue StandardError
|
71
74
|
end
|
72
|
-
rescue StandardError
|
73
75
|
end
|
74
76
|
end
|
75
77
|
|
76
|
-
context '
|
77
|
-
let(:delay) { 1 }
|
78
|
-
|
78
|
+
context 'incremental delay' do
|
79
79
|
it 'sleeps incrementally' do
|
80
|
-
Kernel.should_receive(:sleep).with(1).ordered
|
81
|
-
Kernel.should_receive(:sleep).with(2).ordered
|
82
|
-
Kernel.should_receive(:sleep).with(3).ordered
|
80
|
+
Kernel.should_receive(:sleep).with(0.1).ordered
|
81
|
+
Kernel.should_receive(:sleep).with(0.2).ordered
|
82
|
+
Kernel.should_receive(:sleep).with(0.3).ordered
|
83
83
|
|
84
84
|
begin
|
85
85
|
3.tries on: [FooError, BarError], delay: delay, incremental: true do
|
@@ -90,6 +90,62 @@ describe Tries do
|
|
90
90
|
end
|
91
91
|
end
|
92
92
|
end
|
93
|
+
|
94
|
+
context 'on_error' do
|
95
|
+
context 'when a global callback is set' do
|
96
|
+
it 'calls the global callback with the correct parameters' do
|
97
|
+
global_on_error = Proc.new {}
|
98
|
+
Tries.configure do |config|
|
99
|
+
config.on_error = global_on_error
|
100
|
+
end
|
101
|
+
global_on_error.should_receive(:call).with(an_instance_of(FooError), 1, 0.1).ordered
|
102
|
+
global_on_error.should_receive(:call).with(an_instance_of(FooError), 2, 0.2).ordered
|
103
|
+
global_on_error.should_receive(:call).with(an_instance_of(BarError), 3, 0.3).ordered
|
104
|
+
begin
|
105
|
+
3.tries on: [FooError, BarError], delay: 0.1, incremental: true do
|
106
|
+
raise_foo_foo_bar_bar_standard
|
107
|
+
end
|
108
|
+
rescue StandardError
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'when a local callback is set' do
|
114
|
+
it 'calls the local callback with the correct parameters' do
|
115
|
+
local_on_error = Proc.new {}
|
116
|
+
local_on_error.should_receive(:call).with(an_instance_of(FooError), 1, 0.1).ordered
|
117
|
+
local_on_error.should_receive(:call).with(an_instance_of(FooError), 2, 0.2).ordered
|
118
|
+
local_on_error.should_receive(:call).with(an_instance_of(BarError), 3, 0.3).ordered
|
119
|
+
begin
|
120
|
+
3.tries on: [FooError, BarError], delay: 0.1, incremental: true, on_error: local_on_error do
|
121
|
+
raise_foo_foo_bar_bar_standard
|
122
|
+
end
|
123
|
+
rescue StandardError
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'when both a global and a local callback are set' do
|
129
|
+
it 'calls both callbacks with the correct parameters in the correct order' do
|
130
|
+
local_on_error, global_on_error = Proc.new {}, Proc.new {}
|
131
|
+
global_on_error.should_receive(:call).with(an_instance_of(FooError), 1, 0.1).ordered
|
132
|
+
local_on_error.should_receive(:call).with(an_instance_of(FooError), 1, 0.1).ordered
|
133
|
+
global_on_error.should_receive(:call).with(an_instance_of(FooError), 2, 0.2).ordered
|
134
|
+
local_on_error.should_receive(:call).with(an_instance_of(FooError), 2, 0.2).ordered
|
135
|
+
global_on_error.should_receive(:call).with(an_instance_of(BarError), 3, 0.3).ordered
|
136
|
+
local_on_error.should_receive(:call).with(an_instance_of(BarError), 3, 0.3).ordered
|
137
|
+
Tries.configure do |config|
|
138
|
+
config.on_error = global_on_error
|
139
|
+
end
|
140
|
+
begin
|
141
|
+
3.tries on: [FooError, BarError], delay: 0.1, incremental: true, on_error: local_on_error do
|
142
|
+
raise_foo_foo_bar_bar_standard
|
143
|
+
end
|
144
|
+
rescue StandardError
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
93
149
|
end
|
94
150
|
|
95
151
|
FooError = Class.new(StandardError)
|
data/tries.gemspec
CHANGED
@@ -14,15 +14,16 @@ Gem::Specification.new do |gem|
|
|
14
14
|
gem.summary = 'Solidify your code and retry on petty exceptions'
|
15
15
|
gem.description = 'Solidify your code and retry on petty exceptions'
|
16
16
|
gem.homepage = 'https://github.com/krautcomputing/tries'
|
17
|
+
gem.license = 'MIT'
|
17
18
|
|
18
19
|
gem.files = `git ls-files`.split($/)
|
19
20
|
gem.executables = gem.files.grep(%r(^bin/)).map { |f| File.basename(f) }
|
20
21
|
gem.test_files = gem.files.grep(%r(^(test|spec|features)/))
|
21
22
|
gem.require_paths = ['lib']
|
22
23
|
|
24
|
+
gem.add_development_dependency 'rake', '>= 0.9.0'
|
23
25
|
gem.add_development_dependency 'rspec', '~> 2.13.0'
|
24
|
-
gem.add_development_dependency 'rake', '~> 10.0.1'
|
25
26
|
gem.add_development_dependency 'rb-fsevent', '~> 0.9.2'
|
26
|
-
gem.add_development_dependency 'guard', '~> 1.6.2'
|
27
27
|
gem.add_development_dependency 'guard-rspec', '~> 2.5.0'
|
28
|
+
gem.add_runtime_dependency 'gem_config', '~> 0.2.4'
|
28
29
|
end
|
metadata
CHANGED
@@ -1,85 +1,85 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tries
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Manuel Meurer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
|
15
|
-
name: rspec
|
14
|
+
name: rake
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
16
|
requirements:
|
18
|
-
- -
|
17
|
+
- - '>='
|
19
18
|
- !ruby/object:Gem::Version
|
20
|
-
version:
|
19
|
+
version: 0.9.0
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
21
22
|
version_requirements: !ruby/object:Gem::Requirement
|
22
23
|
requirements:
|
23
|
-
- -
|
24
|
+
- - '>='
|
24
25
|
- !ruby/object:Gem::Version
|
25
|
-
version:
|
26
|
-
type: :development
|
26
|
+
version: 0.9.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
|
29
|
-
name: rake
|
28
|
+
name: rspec
|
30
29
|
requirement: !ruby/object:Gem::Requirement
|
31
30
|
requirements:
|
32
31
|
- - ~>
|
33
32
|
- !ruby/object:Gem::Version
|
34
|
-
version:
|
33
|
+
version: 2.13.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
35
36
|
version_requirements: !ruby/object:Gem::Requirement
|
36
37
|
requirements:
|
37
38
|
- - ~>
|
38
39
|
- !ruby/object:Gem::Version
|
39
|
-
version:
|
40
|
-
type: :development
|
40
|
+
version: 2.13.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
prerelease: false
|
43
42
|
name: rb-fsevent
|
44
43
|
requirement: !ruby/object:Gem::Requirement
|
45
44
|
requirements:
|
46
45
|
- - ~>
|
47
46
|
- !ruby/object:Gem::Version
|
48
47
|
version: 0.9.2
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
49
50
|
version_requirements: !ruby/object:Gem::Requirement
|
50
51
|
requirements:
|
51
52
|
- - ~>
|
52
53
|
- !ruby/object:Gem::Version
|
53
54
|
version: 0.9.2
|
54
|
-
type: :development
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
|
57
|
-
name: guard
|
56
|
+
name: guard-rspec
|
58
57
|
requirement: !ruby/object:Gem::Requirement
|
59
58
|
requirements:
|
60
59
|
- - ~>
|
61
60
|
- !ruby/object:Gem::Version
|
62
|
-
version:
|
61
|
+
version: 2.5.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
63
64
|
version_requirements: !ruby/object:Gem::Requirement
|
64
65
|
requirements:
|
65
66
|
- - ~>
|
66
67
|
- !ruby/object:Gem::Version
|
67
|
-
version:
|
68
|
-
type: :development
|
68
|
+
version: 2.5.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
|
71
|
-
name: guard-rspec
|
70
|
+
name: gem_config
|
72
71
|
requirement: !ruby/object:Gem::Requirement
|
73
72
|
requirements:
|
74
73
|
- - ~>
|
75
74
|
- !ruby/object:Gem::Version
|
76
|
-
version: 2.
|
75
|
+
version: 0.2.4
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
77
78
|
version_requirements: !ruby/object:Gem::Requirement
|
78
79
|
requirements:
|
79
80
|
- - ~>
|
80
81
|
- !ruby/object:Gem::Version
|
81
|
-
version: 2.
|
82
|
-
type: :development
|
82
|
+
version: 0.2.4
|
83
83
|
description: Solidify your code and retry on petty exceptions
|
84
84
|
email: manuel.meurer@gmail.com
|
85
85
|
executables: []
|
@@ -99,7 +99,8 @@ files:
|
|
99
99
|
- spec/tries/tries_spec.rb
|
100
100
|
- tries.gemspec
|
101
101
|
homepage: https://github.com/krautcomputing/tries
|
102
|
-
licenses:
|
102
|
+
licenses:
|
103
|
+
- MIT
|
103
104
|
metadata: {}
|
104
105
|
post_install_message:
|
105
106
|
rdoc_options: []
|
@@ -107,20 +108,21 @@ require_paths:
|
|
107
108
|
- lib
|
108
109
|
required_ruby_version: !ruby/object:Gem::Requirement
|
109
110
|
requirements:
|
110
|
-
- -
|
111
|
+
- - '>='
|
111
112
|
- !ruby/object:Gem::Version
|
112
113
|
version: '0'
|
113
114
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
115
|
requirements:
|
115
|
-
- -
|
116
|
+
- - '>='
|
116
117
|
- !ruby/object:Gem::Version
|
117
118
|
version: '0'
|
118
119
|
requirements: []
|
119
120
|
rubyforge_project:
|
120
|
-
rubygems_version: 2.
|
121
|
+
rubygems_version: 2.1.5
|
121
122
|
signing_key:
|
122
123
|
specification_version: 4
|
123
124
|
summary: Solidify your code and retry on petty exceptions
|
124
125
|
test_files:
|
125
126
|
- spec/spec_helper.rb
|
126
127
|
- spec/tries/tries_spec.rb
|
128
|
+
has_rdoc:
|