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.
@@ -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