rescue_me 0.1.0 → 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.
- data/lib/rescue_me/version.rb +3 -0
- data/lib/rescue_me.rb +34 -7
- metadata +78 -67
- data/.document +0 -5
- data/.gitignore +0 -21
- data/Rakefile +0 -57
- data/VERSION +0 -1
- data/test/helper.rb +0 -10
- data/test/test_rescue_me.rb +0 -86
data/lib/rescue_me.rb
CHANGED
@@ -10,17 +10,16 @@ module Kernel
|
|
10
10
|
# strongly encouraged to provide arguments that capture temporary
|
11
11
|
# exceptional conditions that are likely to work upon a retry.
|
12
12
|
def rescue_and_retry(max_attempts=7, *temporary_exceptions)
|
13
|
-
retry_interval = 2
|
14
|
-
temporary_exceptions <<
|
15
|
-
begin
|
13
|
+
retry_interval = 2 # A good initial start value. Tweak as needed.
|
14
|
+
temporary_exceptions << StandardError if temporary_exceptions.empty?
|
15
|
+
begin
|
16
16
|
yield
|
17
17
|
rescue *temporary_exceptions => e
|
18
18
|
attempt = (attempt || 0) + 1
|
19
|
-
|
20
|
-
|
21
|
-
# TODO AS: Is there a better way to access and use a logger?
|
22
|
-
(defined? logger) ? logger.warn(message) : puts(message)
|
19
|
+
RescueMe::Logger.warn(attempt, max_attempts, caller, e)
|
20
|
+
|
23
21
|
raise(e) if attempt >= max_attempts
|
22
|
+
|
24
23
|
# Retry immediately before exponential waits (1, 2, 4, 16, ... sec)
|
25
24
|
sleep retry_interval**(attempt - 2) if attempt >= 2
|
26
25
|
retry
|
@@ -28,3 +27,31 @@ module Kernel
|
|
28
27
|
end
|
29
28
|
|
30
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
|
+
end
|
metadata
CHANGED
@@ -1,90 +1,101 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: rescue_me
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
- 0
|
10
|
-
version: 0.1.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
prerelease:
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Arild Shirazi
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
12
|
+
date: 2012-12-04 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
22
31
|
name: shoulda
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
23
39
|
prerelease: false
|
24
|
-
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
41
|
none: false
|
26
|
-
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: simplecov
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
33
54
|
type: :development
|
34
|
-
|
35
|
-
|
36
|
-
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: Provides a convenience method to retry blocks of code that might fail
|
63
|
+
due to temporary errors, e.g. a network service that becomes temporarily unavailable.
|
64
|
+
The retries are timed to back-off exponentially (2^n seconds), hopefully giving
|
65
|
+
time for the remote server to recover.
|
66
|
+
email:
|
67
|
+
- as4@eshirazi.com
|
37
68
|
executables: []
|
38
|
-
|
39
69
|
extensions: []
|
40
|
-
|
41
|
-
|
42
|
-
-
|
43
|
-
-
|
44
|
-
files:
|
45
|
-
- .document
|
46
|
-
- .gitignore
|
70
|
+
extra_rdoc_files: []
|
71
|
+
files:
|
72
|
+
- lib/rescue_me/version.rb
|
73
|
+
- lib/rescue_me.rb
|
47
74
|
- LICENSE
|
48
75
|
- README.rdoc
|
49
|
-
|
50
|
-
- VERSION
|
51
|
-
- lib/rescue_me.rb
|
52
|
-
- test/helper.rb
|
53
|
-
- test/test_rescue_me.rb
|
54
|
-
has_rdoc: true
|
55
|
-
homepage: http://github.com/ashirazi/rescue_me
|
76
|
+
homepage: https://github.com/ashirazi/rescue_me
|
56
77
|
licenses: []
|
57
|
-
|
58
78
|
post_install_message:
|
59
|
-
rdoc_options:
|
60
|
-
|
61
|
-
require_paths:
|
79
|
+
rdoc_options: []
|
80
|
+
require_paths:
|
62
81
|
- lib
|
63
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
83
|
none: false
|
65
|
-
requirements:
|
66
|
-
- -
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
|
69
|
-
|
70
|
-
- 0
|
71
|
-
version: "0"
|
72
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
89
|
none: false
|
74
|
-
requirements:
|
75
|
-
- -
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
|
78
|
-
segments:
|
79
|
-
- 0
|
80
|
-
version: "0"
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 1.3.6
|
81
94
|
requirements: []
|
82
|
-
|
83
|
-
|
84
|
-
rubygems_version: 1.3.7
|
95
|
+
rubyforge_project: rescue_me
|
96
|
+
rubygems_version: 1.8.23
|
85
97
|
signing_key:
|
86
98
|
specification_version: 3
|
87
99
|
summary: Retry a block of code that might fail due to temporary errors.
|
88
|
-
test_files:
|
89
|
-
|
90
|
-
- test/test_rescue_me.rb
|
100
|
+
test_files: []
|
101
|
+
has_rdoc:
|
data/.document
DELETED
data/.gitignore
DELETED
data/Rakefile
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'rake'
|
3
|
-
|
4
|
-
begin
|
5
|
-
require 'jeweler'
|
6
|
-
Jeweler::Tasks.new do |gem|
|
7
|
-
gem.name = "rescue_me"
|
8
|
-
gem.summary = %Q{Retry a block of code that might fail due to temporary errors.}
|
9
|
-
gem.description = %Q{Provides a convenience method to retry blocks of code \
|
10
|
-
that might fail due to temporary errors, e.g. a network service that becomes \
|
11
|
-
temporarily unavailable. The retries are timed to back-off exponentially (2^n \
|
12
|
-
seconds), hopefully giving time for the remote server to recover.}
|
13
|
-
gem.email = "as4@eshirazi.com"
|
14
|
-
gem.homepage = "http://github.com/ashirazi/rescue_me"
|
15
|
-
gem.authors = ["Arild Shirazi"]
|
16
|
-
# gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
|
17
|
-
gem.add_development_dependency "shoulda", ">= 0"
|
18
|
-
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
19
|
-
end
|
20
|
-
Jeweler::GemcutterTasks.new
|
21
|
-
rescue LoadError
|
22
|
-
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
23
|
-
end
|
24
|
-
|
25
|
-
require 'rake/testtask'
|
26
|
-
Rake::TestTask.new(:test) do |test|
|
27
|
-
test.libs << 'lib' << 'test'
|
28
|
-
test.pattern = 'test/**/test_*.rb'
|
29
|
-
test.verbose = true
|
30
|
-
end
|
31
|
-
|
32
|
-
begin
|
33
|
-
require 'rcov/rcovtask'
|
34
|
-
Rcov::RcovTask.new do |test|
|
35
|
-
test.libs << 'test'
|
36
|
-
test.pattern = 'test/**/test_*.rb'
|
37
|
-
test.verbose = true
|
38
|
-
end
|
39
|
-
rescue LoadError
|
40
|
-
task :rcov do
|
41
|
-
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
task :test => :check_dependencies
|
46
|
-
|
47
|
-
task :default => :test
|
48
|
-
|
49
|
-
require 'rake/rdoctask'
|
50
|
-
Rake::RDocTask.new do |rdoc|
|
51
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
52
|
-
|
53
|
-
rdoc.rdoc_dir = 'rdoc'
|
54
|
-
rdoc.title = "rescue_me #{version}"
|
55
|
-
rdoc.rdoc_files.include('README*')
|
56
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
57
|
-
end
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.1.0
|
data/test/helper.rb
DELETED
data/test/test_rescue_me.rb
DELETED
@@ -1,86 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
class TestRescueMe < Test::Unit::TestCase
|
4
|
-
|
5
|
-
class ExceptionCounter
|
6
|
-
|
7
|
-
require 'net/smtp'
|
8
|
-
attr_reader :method_called_count
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
@method_called_count = 0;
|
12
|
-
end
|
13
|
-
|
14
|
-
def exception_free
|
15
|
-
@method_called_count += 1
|
16
|
-
"This method does not raise exceptions"
|
17
|
-
end
|
18
|
-
|
19
|
-
def raise_zero_division_error
|
20
|
-
@method_called_count += 1
|
21
|
-
12/0
|
22
|
-
end
|
23
|
-
|
24
|
-
# Will raise SMTPServerBusy the first x times this method is called,
|
25
|
-
# after which this method does nothing.
|
26
|
-
def raise_smtp_exception_until_call(times)
|
27
|
-
@method_called_count += 1
|
28
|
-
@smtp_exception_count = (@smtp_exception_count ||= 0) + 1
|
29
|
-
raise Net::SMTPServerBusy until times > @smtp_exception_count
|
30
|
-
end
|
31
|
-
|
32
|
-
end # ExceptionCounter
|
33
|
-
|
34
|
-
context "rescue_and_retry of code that might raise temporary exceptions" do
|
35
|
-
setup do
|
36
|
-
@exception_counter = ExceptionCounter.new
|
37
|
-
@previous_call_count = @exception_counter.method_called_count
|
38
|
-
end
|
39
|
-
|
40
|
-
should "run an exception-free block of code once" do
|
41
|
-
assert_nothing_raised do
|
42
|
-
rescue_and_retry {
|
43
|
-
@exception_counter.exception_free
|
44
|
-
}
|
45
|
-
end
|
46
|
-
assert 1, @exception_counter.method_called_count
|
47
|
-
end
|
48
|
-
|
49
|
-
should "attempt to run a block that raises an unexpected exception " +
|
50
|
-
"only once" do
|
51
|
-
assert_raise(ZeroDivisionError) do
|
52
|
-
rescue_and_retry(5, IOError) {
|
53
|
-
@exception_counter.raise_zero_division_error
|
54
|
-
}
|
55
|
-
end
|
56
|
-
assert 1, @exception_counter.method_called_count
|
57
|
-
end
|
58
|
-
|
59
|
-
should "re-run the block of code for exactly max_attempt number of times" do
|
60
|
-
assert_raise(ZeroDivisionError) do
|
61
|
-
rescue_and_retry(3, IOError) {
|
62
|
-
@exception_counter.raise_zero_division_error
|
63
|
-
}
|
64
|
-
end
|
65
|
-
assert 3, @exception_counter.method_called_count - @previous_call_count
|
66
|
-
|
67
|
-
assert_raise(ZeroDivisionError) do
|
68
|
-
rescue_and_retry(1, IOError) {
|
69
|
-
@exception_counter.raise_zero_division_error
|
70
|
-
}
|
71
|
-
end
|
72
|
-
assert 1, @exception_counter.method_called_count - @previous_call_count
|
73
|
-
end
|
74
|
-
|
75
|
-
should "not re-run the block of code after it has run successfully" do
|
76
|
-
assert_nothing_raised do
|
77
|
-
rescue_and_retry(5, Net::SMTPServerBusy) {
|
78
|
-
@exception_counter.raise_smtp_exception_until_call(3)
|
79
|
-
}
|
80
|
-
end
|
81
|
-
assert 3, @exception_counter.method_called_count
|
82
|
-
end
|
83
|
-
|
84
|
-
end
|
85
|
-
|
86
|
-
end
|