zeevex_reliability 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.
@@ -14,7 +14,7 @@ module ZeevexReliability
|
|
14
14
|
# # your code here
|
15
15
|
# end
|
16
16
|
#
|
17
|
-
def self.
|
17
|
+
def self.retryable(options = {}, &block)
|
18
18
|
opts = { :tries => 3, :on => StandardError }.merge(options)
|
19
19
|
|
20
20
|
retry_exception, retries = opts[:on], opts[:tries]
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper.rb')
|
4
|
+
|
5
|
+
require 'logger'
|
6
|
+
|
7
|
+
class RunnerModel
|
8
|
+
|
9
|
+
include ZeevexReliability::OptimisticLockRetryable
|
10
|
+
|
11
|
+
def initialize(retry_count = 2)
|
12
|
+
@retry_count = retry_count
|
13
|
+
@executed = 0
|
14
|
+
@reload_count = 0
|
15
|
+
end
|
16
|
+
|
17
|
+
def execution_count
|
18
|
+
@executed
|
19
|
+
end
|
20
|
+
|
21
|
+
def succeed_at_once
|
22
|
+
@executed += 1
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
def never_succeed(error = ActiveRecord::StaleObjectError)
|
27
|
+
@executed += 1
|
28
|
+
raise error
|
29
|
+
end
|
30
|
+
|
31
|
+
def succeed_eventually(error = ActiveRecord::StaleObjectError)
|
32
|
+
@executed += 1
|
33
|
+
|
34
|
+
return true if @retry_count == 0
|
35
|
+
@retry_count -= 1
|
36
|
+
raise error
|
37
|
+
end
|
38
|
+
|
39
|
+
def reload
|
40
|
+
@reload_count += 1
|
41
|
+
end
|
42
|
+
|
43
|
+
def reload!
|
44
|
+
reload
|
45
|
+
end
|
46
|
+
|
47
|
+
def changed?
|
48
|
+
false
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
describe ZeevexReliability::OptimisticLockRetryable do
|
54
|
+
|
55
|
+
let :logger do
|
56
|
+
Logger.new("/dev/null")
|
57
|
+
end
|
58
|
+
|
59
|
+
let :runner do
|
60
|
+
RunnerModel.new
|
61
|
+
end
|
62
|
+
|
63
|
+
context "without error" do
|
64
|
+
it "should execute once and succeed" do
|
65
|
+
runner.with_optimistic_retry do
|
66
|
+
runner.succeed_at_once
|
67
|
+
end.should == true
|
68
|
+
runner.execution_count.should == 1
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "caught error" do
|
73
|
+
it "when block fails twice and then succeeds, should return true" do
|
74
|
+
runner.should_receive(:reload).twice.and_return(true)
|
75
|
+
|
76
|
+
runner.with_optimistic_retry do
|
77
|
+
runner.succeed_eventually
|
78
|
+
end.should == true
|
79
|
+
runner.execution_count.should == 3
|
80
|
+
end
|
81
|
+
|
82
|
+
it "when block fails twice and then succeeds, should return true" do
|
83
|
+
runner.should_receive(:changed?).and_return(true)
|
84
|
+
runner.should_receive(:logger).and_return(logger)
|
85
|
+
logger.should_receive(:warn).once
|
86
|
+
|
87
|
+
runner.with_optimistic_retry do
|
88
|
+
runner.succeed_eventually
|
89
|
+
end.should == true
|
90
|
+
end
|
91
|
+
|
92
|
+
it "when block always fails, it should stop after 3 tries then re-raise error" do
|
93
|
+
expect {
|
94
|
+
runner.with_optimistic_retry do
|
95
|
+
runner.never_succeed
|
96
|
+
end
|
97
|
+
}.to raise_error(ActiveRecord::StaleObjectError)
|
98
|
+
runner.execution_count.should == 3
|
99
|
+
end
|
100
|
+
|
101
|
+
it "when block always fails, it should stop after # of tries specified then re-raise error" do
|
102
|
+
expect {
|
103
|
+
runner.with_optimistic_retry(:tries => 10) do
|
104
|
+
runner.never_succeed
|
105
|
+
end
|
106
|
+
}.to raise_error(ActiveRecord::StaleObjectError)
|
107
|
+
runner.execution_count.should == 10
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context "uncaught error" do
|
112
|
+
it "should fail once and not retry" do
|
113
|
+
expect {
|
114
|
+
runner.with_optimistic_retry do
|
115
|
+
runner.never_succeed(NameError)
|
116
|
+
end
|
117
|
+
}.to raise_error(NameError)
|
118
|
+
runner.execution_count.should == 1
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper.rb')
|
4
|
+
|
5
|
+
class Runner
|
6
|
+
def initialize(retry_count = 2)
|
7
|
+
@retry_count = retry_count
|
8
|
+
@executed = 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def execution_count
|
12
|
+
@executed
|
13
|
+
end
|
14
|
+
|
15
|
+
def succeed_at_once
|
16
|
+
@executed += 1
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def never_succeed(error = ArgumentError)
|
21
|
+
@executed += 1
|
22
|
+
raise error
|
23
|
+
end
|
24
|
+
|
25
|
+
def succeed_eventually(error = ArgumentError)
|
26
|
+
@executed += 1
|
27
|
+
|
28
|
+
return true if @retry_count == 0
|
29
|
+
@retry_count -= 1
|
30
|
+
raise error
|
31
|
+
end
|
32
|
+
|
33
|
+
def raise_known
|
34
|
+
raise ArgumentError
|
35
|
+
end
|
36
|
+
|
37
|
+
def raise_unknown
|
38
|
+
raise "Just some other thing"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe ZeevexReliability::Retryable do
|
43
|
+
|
44
|
+
let :runner do
|
45
|
+
Runner.new
|
46
|
+
end
|
47
|
+
|
48
|
+
context "without error" do
|
49
|
+
it "should execute once and succeed" do
|
50
|
+
ZeevexReliability::Retryable.retryable do
|
51
|
+
runner.succeed_at_once
|
52
|
+
end.should == true
|
53
|
+
runner.execution_count.should == 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "caught error" do
|
58
|
+
it "when block fails twice and then succeeds, should return true" do
|
59
|
+
ZeevexReliability::Retryable.retryable(:on => ArgumentError) do
|
60
|
+
runner.succeed_eventually
|
61
|
+
end.should == true
|
62
|
+
runner.execution_count.should == 3
|
63
|
+
end
|
64
|
+
|
65
|
+
it "when block always fails, it should stop after 3 tries then re-raise error" do
|
66
|
+
expect {
|
67
|
+
ZeevexReliability::Retryable.retryable(:on => ArgumentError) do
|
68
|
+
runner.never_succeed
|
69
|
+
end
|
70
|
+
}.to raise_error(ArgumentError)
|
71
|
+
runner.execution_count.should == 3
|
72
|
+
end
|
73
|
+
|
74
|
+
it "when block always fails, it should stop after # of tries specified then re-raise error" do
|
75
|
+
expect {
|
76
|
+
ZeevexReliability::Retryable.retryable(:on => ArgumentError, :tries => 10) do
|
77
|
+
runner.never_succeed
|
78
|
+
end
|
79
|
+
}.to raise_error(ArgumentError)
|
80
|
+
runner.execution_count.should == 10
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context "uncaught error" do
|
85
|
+
it "should fail once and not retry" do
|
86
|
+
expect {
|
87
|
+
ZeevexReliability::Retryable.retryable(:on => NameError) do
|
88
|
+
runner.never_succeed
|
89
|
+
end
|
90
|
+
}.to raise_error(ArgumentError)
|
91
|
+
runner.execution_count.should == 1
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 1
|
9
|
+
version: 0.1.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Robert Sanders
|
@@ -74,6 +74,9 @@ files:
|
|
74
74
|
- lib/zeevex_reliability/optimistic_lock_retryable.rb
|
75
75
|
- lib/zeevex_reliability/retryable.rb
|
76
76
|
- lib/zeevex_reliability/version.rb
|
77
|
+
- spec/optimistic_lock_retryable_spec.rb
|
78
|
+
- spec/retryable_spec.rb
|
79
|
+
- spec/spec_helper.rb
|
77
80
|
- zeevex_reliability.gemspec
|
78
81
|
has_rdoc: true
|
79
82
|
homepage: ""
|
@@ -105,5 +108,7 @@ rubygems_version: 1.3.6
|
|
105
108
|
signing_key:
|
106
109
|
specification_version: 3
|
107
110
|
summary: Utility functions to automate retry loops
|
108
|
-
test_files:
|
109
|
-
|
111
|
+
test_files:
|
112
|
+
- spec/optimistic_lock_retryable_spec.rb
|
113
|
+
- spec/retryable_spec.rb
|
114
|
+
- spec/spec_helper.rb
|