rescue_me 0.1.1 → 0.1.2
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/.document +5 -0
- data/.gitignore +21 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE +18 -22
- data/README.rdoc +4 -27
- data/Rakefile +6 -0
- data/lib/rescue_me/version.rb +1 -1
- data/lib/rescue_me.rb +5 -33
- data/pkg/.gitignore +1 -0
- data/rescue_me.gemspec +26 -0
- data/spec/rescue_me_spec.rb +85 -0
- data/spec/spec_helper.rb +6 -0
- metadata +52 -8
data/.document
ADDED
data/.gitignore
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.9.3-p194
|
data/Gemfile
ADDED
data/LICENSE
CHANGED
@@ -1,26 +1,22 @@
|
|
1
|
-
Copyright (c) 2010 Arild Shirazi
|
1
|
+
Copyright (c) 2010 Arild Shirazi
|
2
2
|
|
3
|
-
|
4
|
-
are permitted provided that the following conditions are met:
|
3
|
+
MIT License
|
5
4
|
|
6
|
-
|
7
|
-
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
8
12
|
|
9
|
-
|
10
|
-
|
11
|
-
and/or other materials provided with the distribution.
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
12
15
|
|
13
|
-
|
14
|
-
|
15
|
-
MERCHANTABILITY
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
21
|
-
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
22
|
-
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
23
|
-
|
24
|
-
The views and conclusions contained in the software and documentation are those
|
25
|
-
of the authors and should not be interpreted as representing official policies,
|
26
|
-
either expressed or implied, of Arild Shirazi.
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
CHANGED
@@ -19,9 +19,9 @@ following 2 network errors:
|
|
19
19
|
}
|
20
20
|
|
21
21
|
Log output:
|
22
|
-
WARN -- :
|
23
|
-
WARN -- :
|
24
|
-
WARN -- :
|
22
|
+
WARN -- : rescue_and_retry(1/5) "SMTPServerBusy: 451 4.3.0 Mail server temporarily rejected message." in ./mailer.rb:43
|
23
|
+
WARN -- : rescue_and_retry(2/5) "SMTPServerBusy: 451 4.3.0 Mail server temporarily rejected message." in ./mailer.rb:43
|
24
|
+
WARN -- : rescue_and_retry(3/5) "SMTPServerBusy: 451 4.3.0 Mail server temporarily rejected message." in ./mailer.rb:43
|
25
25
|
# No further output or stacktrace. Block succeeded on 4th attempt.
|
26
26
|
|
27
27
|
|
@@ -29,27 +29,4 @@ Log output:
|
|
29
29
|
|
30
30
|
Copyright (c) 2010 Arild Shirazi. All rights reserved.
|
31
31
|
|
32
|
-
|
33
|
-
are permitted provided that the following conditions are met:
|
34
|
-
|
35
|
-
1. Redistributions of source code must retain the above copyright notice,
|
36
|
-
this list of conditions and the following disclaimer.
|
37
|
-
|
38
|
-
2. Redistributions in binary form must reproduce the above copyright notice,
|
39
|
-
this list of conditions and the following disclaimer in the documentation
|
40
|
-
and/or other materials provided with the distribution.
|
41
|
-
|
42
|
-
THIS SOFTWARE IS PROVIDED BY ARILD SHIRAZI ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
43
|
-
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
44
|
-
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
45
|
-
SHALL ARILD SHIRAZI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
46
|
-
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
47
|
-
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
48
|
-
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
49
|
-
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
50
|
-
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
51
|
-
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
52
|
-
|
53
|
-
The views and conclusions contained in the software and documentation are those
|
54
|
-
of the authors and should not be interpreted as representing official policies,
|
55
|
-
either expressed or implied, of Arild Shirazi.
|
32
|
+
See LICENSE for details.
|
data/Rakefile
ADDED
data/lib/rescue_me/version.rb
CHANGED
data/lib/rescue_me.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
require "rescue_me/version"
|
2
2
|
|
3
|
+
module Kernel
|
3
4
|
# Reattempts to run code passed in to this block if a temporary exception occurs
|
4
5
|
# (e.g. Net::SMTPServerBusy), using an exponential back-off algorithm
|
5
6
|
# (e.g. retry immediately, then after 1, 2, 4, 8, 16, 32... sec).
|
@@ -16,42 +17,13 @@ module Kernel
|
|
16
17
|
yield
|
17
18
|
rescue *temporary_exceptions => e
|
18
19
|
attempt = (attempt || 0) + 1
|
19
|
-
|
20
|
-
|
20
|
+
message = "rescue_and_retry(#{attempt}/#{max_attempts}) " +
|
21
|
+
"\"#{e.class}: #{e.message}\" in #{caller[1].sub(/.*\/(.*):in.*/,'\1')}"
|
22
|
+
(defined? logger) ? logger.warn(message) : STDERR.puts(message)
|
21
23
|
raise(e) if attempt >= max_attempts
|
22
|
-
|
23
24
|
# Retry immediately before exponential waits (1, 2, 4, 16, ... sec)
|
24
25
|
sleep retry_interval**(attempt - 2) if attempt >= 2
|
25
26
|
retry
|
26
27
|
end
|
27
28
|
end
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
module RescueMe
|
32
|
-
require "logger"
|
33
|
-
|
34
|
-
class << self
|
35
|
-
def logger
|
36
|
-
@logger ||= defined?(Rails) && Rails.respond_to?(:logger) ? Rails.logger : ::Logger.new($stdout)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
module Logger
|
41
|
-
|
42
|
-
class << self
|
43
|
-
def warn(attempt, max_attempts, kaller, exception)
|
44
|
-
if RescueMe.logger && RescueMe.logger.respond_to?(:warn)
|
45
|
-
RescueMe.logger.warn(rescued_message(attempt, max_attempts, kaller, exception))
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def rescued_message(attempt, max_attempts, kaller, exception)
|
50
|
-
"rescue and retry (attempt #{attempt}/#{max_attempts}): " +
|
51
|
-
"#{kaller.first}, <#{exception.class}: #{exception.message}>"
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
29
|
end
|
data/pkg/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
data/rescue_me.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rescue_me/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'rescue_me'
|
8
|
+
spec.version = RescueMe::VERSION
|
9
|
+
spec.authors = ['Arild Shirazi']
|
10
|
+
spec.email = ['as4@eshirazi.com']
|
11
|
+
spec.description = 'Provides a convenience method to retry blocks of code that might fail due to temporary errors, e.g. a network service that becomes temporarily unavailable. The retries are timed to back-off exponentially (2^n seconds), hopefully giving time for the remote server to recover.'
|
12
|
+
spec.summary = 'Retry a block of code that might fail due to temporary errors.'
|
13
|
+
spec.homepage = 'https://github.com/ashirazi/rescue_me'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency 'bundler'
|
22
|
+
spec.add_development_dependency 'rake'
|
23
|
+
spec.add_development_dependency 'rspec'
|
24
|
+
spec.add_development_dependency 'shoulda'
|
25
|
+
spec.add_development_dependency 'simplecov'
|
26
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
# TODO AS: Replace this class with a mock
|
4
|
+
class ExceptionCounter
|
5
|
+
|
6
|
+
require 'net/smtp'
|
7
|
+
attr_reader :method_called_count
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@method_called_count = 0
|
11
|
+
end
|
12
|
+
|
13
|
+
def exception_free
|
14
|
+
@method_called_count += 1
|
15
|
+
"This method does not raise exceptions"
|
16
|
+
end
|
17
|
+
|
18
|
+
def raise_zero_division_error
|
19
|
+
@method_called_count += 1
|
20
|
+
12/0
|
21
|
+
end
|
22
|
+
|
23
|
+
# Will raise SMTPServerBusy the first x times this method is called,
|
24
|
+
# after which this method does nothing.
|
25
|
+
def raise_smtp_exception_until_call(times)
|
26
|
+
@method_called_count += 1
|
27
|
+
@smtp_exception_count = (@smtp_exception_count ||= 0) + 1
|
28
|
+
raise Net::SMTPServerBusy if times > @smtp_exception_count
|
29
|
+
end
|
30
|
+
|
31
|
+
end # ExceptionCounter
|
32
|
+
|
33
|
+
describe 'rescue_me' do
|
34
|
+
|
35
|
+
before(:each) do
|
36
|
+
@exception_counter = ExceptionCounter.new
|
37
|
+
end
|
38
|
+
|
39
|
+
it "runs an exception-free block of code once" do
|
40
|
+
rescue_and_retry {
|
41
|
+
@exception_counter.exception_free
|
42
|
+
}
|
43
|
+
@exception_counter.method_called_count.should == 1
|
44
|
+
end
|
45
|
+
|
46
|
+
it "attempts to run a block that raises an unexpected exception only once" do
|
47
|
+
expect do
|
48
|
+
rescue_and_retry(5, IOError) {
|
49
|
+
@exception_counter.raise_zero_division_error
|
50
|
+
}
|
51
|
+
end.to raise_error ZeroDivisionError
|
52
|
+
@exception_counter.method_called_count.should == 1
|
53
|
+
end
|
54
|
+
|
55
|
+
it "re-runs the block of code for exactly max_attempt number of times" do
|
56
|
+
begin
|
57
|
+
rescue_and_retry(3, ZeroDivisionError) {
|
58
|
+
@exception_counter.raise_zero_division_error
|
59
|
+
}
|
60
|
+
rescue
|
61
|
+
end
|
62
|
+
@exception_counter.method_called_count.should == 3
|
63
|
+
end
|
64
|
+
|
65
|
+
it "re-runs the block of code for exactly a single time when specified" do
|
66
|
+
@exception_counter = ExceptionCounter.new
|
67
|
+
begin
|
68
|
+
rescue_and_retry(1, ZeroDivisionError) {
|
69
|
+
@exception_counter.raise_zero_division_error
|
70
|
+
}
|
71
|
+
rescue
|
72
|
+
end
|
73
|
+
@exception_counter.method_called_count.should == 1
|
74
|
+
end
|
75
|
+
|
76
|
+
it "does not re-run the block of code after it has run successfully" do
|
77
|
+
expect do
|
78
|
+
rescue_and_retry(5, Net::SMTPServerBusy) {
|
79
|
+
@exception_counter.raise_smtp_exception_until_call(3)
|
80
|
+
}
|
81
|
+
end.to_not raise_error
|
82
|
+
@exception_counter.method_called_count.should == 3
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rescue_me
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-03-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -27,6 +27,38 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
30
62
|
- !ruby/object:Gem::Dependency
|
31
63
|
name: shoulda
|
32
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -69,12 +101,22 @@ executables: []
|
|
69
101
|
extensions: []
|
70
102
|
extra_rdoc_files: []
|
71
103
|
files:
|
72
|
-
-
|
73
|
-
-
|
104
|
+
- .document
|
105
|
+
- .gitignore
|
106
|
+
- .ruby-version
|
107
|
+
- Gemfile
|
74
108
|
- LICENSE
|
75
109
|
- README.rdoc
|
110
|
+
- Rakefile
|
111
|
+
- lib/rescue_me.rb
|
112
|
+
- lib/rescue_me/version.rb
|
113
|
+
- pkg/.gitignore
|
114
|
+
- rescue_me.gemspec
|
115
|
+
- spec/rescue_me_spec.rb
|
116
|
+
- spec/spec_helper.rb
|
76
117
|
homepage: https://github.com/ashirazi/rescue_me
|
77
|
-
licenses:
|
118
|
+
licenses:
|
119
|
+
- MIT
|
78
120
|
post_install_message:
|
79
121
|
rdoc_options: []
|
80
122
|
require_paths:
|
@@ -90,12 +132,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
90
132
|
requirements:
|
91
133
|
- - ! '>='
|
92
134
|
- !ruby/object:Gem::Version
|
93
|
-
version:
|
135
|
+
version: '0'
|
94
136
|
requirements: []
|
95
|
-
rubyforge_project:
|
137
|
+
rubyforge_project:
|
96
138
|
rubygems_version: 1.8.23
|
97
139
|
signing_key:
|
98
140
|
specification_version: 3
|
99
141
|
summary: Retry a block of code that might fail due to temporary errors.
|
100
|
-
test_files:
|
142
|
+
test_files:
|
143
|
+
- spec/rescue_me_spec.rb
|
144
|
+
- spec/spec_helper.rb
|
101
145
|
has_rdoc:
|