pester 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f5c9151d53d657939d6506baf8a27e5da2744b3b
4
- data.tar.gz: 251a6215cfe9cd275f37bf7df458561116cb7401
3
+ metadata.gz: c726cd4ef970107604a3cabf1d26ddf04fffbc45
4
+ data.tar.gz: 3579a4065f03f7791720e9d98d0c6bdc5a3c57f7
5
5
  SHA512:
6
- metadata.gz: dd350670630f082f40af4ab8290e7eb5f8a75a2137ca61cacc63c72445c28baad2eda3bc595aec14bb2782bc3ac5778a38c5678661aaec77ab75fe9f1fcb7e9f
7
- data.tar.gz: 4bd76629e817aca9981340564ec5426ab8e6c6619bbe222b6b7b0d33143e587f21c9b49a31d2dbfb87d9a06ac1863dcf192d550860cf7686ba56448dc38041e0
6
+ metadata.gz: 3e6af9161e42c15a613748d81845adfa8d786b4a5309b41163b87c5d42945968e984e66e84a95f9ba141b2a713c1c30f1a2d5c6b8b8648e516fc1cb0931b84d0
7
+ data.tar.gz: a5719117192311422b5bce432f1b53cef9d98f12ef3b4e1df6b244d237709353ce64af6152c015b75910226b010119abadd890cc23a5f15eeebf34c441b0f450
@@ -1,3 +1,3 @@
1
1
  module Pester
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
data/lib/pester.rb CHANGED
@@ -26,6 +26,10 @@ module Pester
26
26
  # Options:
27
27
  # retry_error_classes - A single or array of exceptions to retry on. Thrown exceptions not in this list
28
28
  # (including parent/sub-classes) will be reraised
29
+ # retry_error_messages - A single or array of exception messages to retry on. If only this options is passed,
30
+ # any exception with a message containing one of these strings will be retried. If this
31
+ # option is passed along with retry_error_classes, retry will only happen when both the
32
+ # class and the message match the exception. Strings and regexes are both permitted.
29
33
  # reraise_error_classes - A single or array of exceptions to always re-raiseon. Thrown exceptions not in
30
34
  # this list (including parent/sub-classes) will be retried
31
35
  # max_attempts - Max number of attempts to retry
@@ -33,18 +37,14 @@ module Pester
33
37
  # passed to retry_with_backoff will retry first after 2 seconds, then 4, then 6, et al.
34
38
  # on_retry - A Proc to be called on each successive failure, before the next retry
35
39
  # on_max_attempts_exceeded - A Proc to be called when attempt_num >= max_attempts - 1
36
- # message - String or regex to look for in thrown exception messages. Matches will trigger retry
37
- # logic, non-matches will cause the exception to be reraised
40
+ # logger - Where to log the output
38
41
  #
39
42
  # Usage:
40
- # retry_action do
43
+ # retry_action(retry_error_classes: [Mysql2::Error]) do
41
44
  # puts 'trying to remove a directory'
42
45
  # FileUtils.rm_r(directory)
43
46
  # end
44
- #
45
- # retryable(error_classes: Mysql2::Error, message: /^Lost connection to MySQL server/, max_attempts: 2) do
46
- # ActiveRecord::Base.connection.execute("LONG MYSQL STATEMENT")
47
- # end
47
+
48
48
  def self.retry_action(opts = {}, &block)
49
49
  merge_defaults(opts)
50
50
  if opts[:retry_error_classes] && opts[:reraise_error_classes]
@@ -53,16 +53,10 @@ module Pester
53
53
 
54
54
  opts[:max_attempts].times do |attempt_num|
55
55
  begin
56
- result = yield block
57
- return result
56
+ return yield(block)
58
57
  rescue => e
59
- class_reraise = opts[:retry_error_classes] && !opts[:retry_error_classes].include?(e.class)
60
- reraise_error = opts[:reraise_error_classes] && opts[:reraise_error_classes].include?(e.class)
61
- message_reraise = opts[:message] && !e.message[opts[:message]]
62
-
63
- if class_reraise || message_reraise || reraise_error
64
- match_type = class_reraise ? 'class' : 'message'
65
- opts[:logger].warn("Reraising exception from inside retry_action because provided #{match_type} was not matched.")
58
+ unless should_retry?(e, opts)
59
+ opts[:logger].warn('Reraising exception from inside retry_action.')
66
60
  raise
67
61
  end
68
62
 
@@ -72,6 +66,7 @@ module Pester
72
66
  opts[:logger].warn("Failure encountered: #{e}, backing off and trying again #{attempts_left} more times. Trace: #{trace}")
73
67
  opts[:on_retry].call(attempt_num, opts[:delay_interval])
74
68
  else
69
+ # Careful here because you will get back the return value of the on_max_attempts_exceeded proc!
75
70
  return opts[:on_max_attempts_exceeded].call(opts[:logger], opts[:max_attempts], e)
76
71
  end
77
72
  end
@@ -80,8 +75,29 @@ module Pester
80
75
 
81
76
  private
82
77
 
78
+ def self.should_retry?(e, opts = {})
79
+ retry_error_classes = opts[:retry_error_classes]
80
+ retry_error_messages = opts[:retry_error_messages]
81
+ reraise_error_classes = opts[:reraise_error_classes]
82
+
83
+ if retry_error_classes
84
+ if retry_error_messages
85
+ retry_error_classes.include?(e.class) && retry_error_messages.any? { |m| e.message[m] }
86
+ else
87
+ retry_error_classes.include?(e.class)
88
+ end
89
+ elsif retry_error_messages
90
+ retry_error_messages.any? { |m| e.message[m] }
91
+ elsif reraise_error_classes && reraise_error_classes.include?(e.class)
92
+ false
93
+ else
94
+ true
95
+ end
96
+ end
97
+
83
98
  def self.merge_defaults(opts)
84
99
  opts[:retry_error_classes] = opts[:retry_error_classes] ? Array(opts[:retry_error_classes]) : nil
100
+ opts[:retry_error_messages] = opts[:retry_error_messages] ? Array(opts[:retry_error_messages]) : nil
85
101
  opts[:reraise_error_classes] = opts[:reraise_error_classes] ? Array(opts[:reraise_error_classes]) : nil
86
102
  opts[:max_attempts] ||= 4
87
103
  opts[:delay_interval] ||= 30
data/spec/pester_spec.rb CHANGED
@@ -55,7 +55,6 @@ shared_examples 'raises an error only in the correct cases with a retry class' d
55
55
  let(:actual_error_message) { matching_error_message }
56
56
 
57
57
  it_has_behavior "doesn't raise an error"
58
-
59
58
  it_has_behavior 'returns and succeeds'
60
59
  end
61
60
  end
@@ -66,7 +65,6 @@ shared_examples 'raises an error only in the correct cases with a reraise class'
66
65
  let(:actual_error_message) { non_matching_error_message }
67
66
 
68
67
  it_has_behavior "doesn't raise an error"
69
-
70
68
  it_has_behavior 'returns and succeeds'
71
69
  end
72
70
 
@@ -88,7 +86,6 @@ describe 'retry_action' do
88
86
  let(:options) { { delay_interval: 0, logger: null_logger } }
89
87
 
90
88
  it_has_behavior "doesn't raise an error"
91
-
92
89
  it_has_behavior 'returns and succeeds'
93
90
  end
94
91
 
@@ -97,7 +94,6 @@ describe 'retry_action' do
97
94
  let(:options) { { max_attempts: 3, logger: null_logger } }
98
95
 
99
96
  it_has_behavior "doesn't raise an error"
100
-
101
97
  it_has_behavior 'returns and succeeds'
102
98
  end
103
99
 
@@ -111,17 +107,34 @@ describe 'retry_action' do
111
107
  it_has_behavior 'raises an error'
112
108
  end
113
109
 
114
- context 'with on_max_attempts_exceeded specified (which does not raise)' do
115
- let(:do_nothing_proc) { proc {} }
110
+ context 'with on_max_attempts_exceeded proc specified' do
116
111
  let(:options) do
117
112
  {
118
113
  max_attempts: max_attempts,
119
- on_max_attempts_exceeded: do_nothing_proc,
114
+ on_max_attempts_exceeded: proc_to_call,
120
115
  logger: null_logger
121
116
  }
122
117
  end
123
118
 
124
- it_has_behavior "doesn't raise an error"
119
+ context 'which does not do anything' do
120
+ let(:proc_to_call) { proc {} }
121
+ it_has_behavior "doesn't raise an error"
122
+ end
123
+
124
+ context 'which reraises' do
125
+ let(:proc_to_call) { Behaviors::WarnAndReraise }
126
+ it_has_behavior 'raises an error'
127
+ end
128
+
129
+ context 'which returns a value' do
130
+ let(:return_value) { 'return_value' }
131
+ let(:proc_to_call) { proc { return_value } }
132
+ it_has_behavior "doesn't raise an error"
133
+
134
+ it 'should return the result of the proc' do
135
+ expect(Pester.retry_action(options) { action }).to eq(return_value)
136
+ end
137
+ end
125
138
  end
126
139
  end
127
140
 
@@ -138,7 +151,7 @@ describe 'retry_action' do
138
151
  let(:options) do
139
152
  {
140
153
  retry_error_classes: expected_error_classes,
141
- message: /^Lost connection to MySQL server/,
154
+ retry_error_messages: /^Lost connection to MySQL server/,
142
155
  max_attempts: 10,
143
156
  logger: null_logger
144
157
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pester
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marc Bollinger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-30 00:00:00.000000000 Z
11
+ date: 2015-04-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler