zeevex_reliability 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,8 @@
1
1
  module ZeevexReliability
2
2
  module OptimisticLockRetryable
3
3
  def self.included(base)
4
+ require 'active_record'
5
+ require 'active_record/base'
4
6
  base.class_eval do
5
7
  include InstanceMethods
6
8
  end
@@ -14,7 +14,7 @@ module ZeevexReliability
14
14
  # # your code here
15
15
  # end
16
16
  #
17
- def self.retry(options = {}, &block)
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]
@@ -1,3 +1,3 @@
1
1
  module ZeevexReliability
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -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
@@ -0,0 +1,8 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ $: << File.expand_path(File.dirname(__FILE__) + '../lib')
4
+
5
+ require 'rspec'
6
+ require 'active_record'
7
+
8
+ require 'zeevex_reliability'
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 0
9
- version: 0.1.0
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