pester 0.2.0 → 1.0.0

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: 72934e84c8c0e2fd2f04a00cf0bf813514e22ee6
4
- data.tar.gz: 67bdc3fd419f71dd3e5f9e4a49b507eeb97fd083
3
+ metadata.gz: f1f5ea594c429a04f50888d1869f4e829db2995a
4
+ data.tar.gz: 18eb22f587bcc68d708872c085d6f16ab746fc9c
5
5
  SHA512:
6
- metadata.gz: 2912019dd882c9f0d7f180e8de1c116efcad81af40ddccacdf39c81fc74250cd817f743a402ddb1e3a178da886e50322011d41815021c3ab7551ffd2a5372ade
7
- data.tar.gz: 39fc544569277ab0b22972342a480196292155eab48bf4b6c583012608d851fbf69ed3b663099657d6f38dbadfdbc21fe71fadaa3650cdb2c166e83bb7e02fe5
6
+ metadata.gz: 6150fbb4bf53a271945524e42b1672951e018a18a1505c61407dbed0f322862e4181260502009695d87e9d21aac3587c42e5b2ad6766b1f9a8622bcea62c5f7e
7
+ data.tar.gz: 4cb89d7f6d88e2591efbca5f57b513e5bb5111f902f33225c4b827174ef60e8902738e9be6750058f8d7581b16fa0b05bcb82a7e1fa16bb56c24ba8214094d3a
@@ -1,14 +1,29 @@
1
1
  Metrics/AbcSize:
2
- Max: 20
2
+ Max: 27
3
+
4
+ Metrics/CyclomaticComplexity:
5
+ Max: 7
3
6
 
4
7
  Metrics/LineLength:
5
8
  Max: 140
6
9
 
10
+ Metrics/MethodLength:
11
+ Max: 23
12
+
13
+ Metrics/PerceivedComplexity:
14
+ Max: 9
15
+
7
16
  Style/Documentation:
8
- Enabled: false
17
+ Enabled: false
18
+
19
+ Style/ModuleFunction:
20
+ Enabled: false
9
21
 
10
22
  Style/RaiseArgs:
11
- Enabled: false
23
+ Enabled: false
24
+
25
+ Style/SpaceAroundOperators:
26
+ Enabled: false
12
27
 
13
28
  Style/SignalException:
14
29
  Enabled: false
data/README.md CHANGED
@@ -11,7 +11,7 @@ From the outset, the goal of Pester is to offer a simple interface. For example:
11
11
 
12
12
  irb(main):001:0> require 'pester'
13
13
  => true
14
- irb(main):002:0> Pester.retry { fail 'derp' }
14
+ irb(main):002:0> Pester.retry_constant { fail 'derp' }
15
15
  W, [2015-04-04T10:37:46.413158 #87600] WARN -- : Failure encountered: derp, backing off and trying again 3 more times. etc etc
16
16
 
17
17
  will retry the block--which always fails--until Pester has exhausted its amount of retries. With no options provided, this will sleep for a constant number of seconds between attempts.
@@ -24,7 +24,7 @@ Pester's basic retry behaviors are defined by three options:
24
24
 
25
25
  `delay_interval` is the unit, in seconds, that will be delayed between attempts. Normally, this is just the total number of seconds, but it can change with other `Behavior`s. `max_attempts` is the number of tries Pester will make, including the initial one. If this is set to 1, Pester will basically not retry; less than 1, it will not even bother executing the block:
26
26
 
27
- irb(main):001:0> Pester.retry(max_attempts: 0) { puts 'Trying...'; fail 'derp' }
27
+ irb(main):001:0> Pester.retry_constant(max_attempts: 0) { puts 'Trying...'; fail 'derp' }
28
28
  => nil
29
29
 
30
30
  `on_retry` defines the behavior between retries, which can either be a custom block of code, or one of the predefined `Behavior`s, specifically in `Pester::Behaviors::Sleep`. If passed an empty lambda/block, Pester will immediately retry. When writing a custom behavior, `on_retry` expects a block that can be called with two parameters, `attempt_num`, and `delay_interval`, the idea being that these will mostly be used to define a function that determines just how long to sleep between attempts.
@@ -35,7 +35,7 @@ Three behaviors are provided out-of-the box:
35
35
  * `Linear` simply multiplies `attempt_num` by `delay_interval` and sleeps for that many seconds
36
36
  * `Exponential` sleeps for 2<sup>(`attempt_num` - 1)</sup> * `delay_interval` seconds
37
37
 
38
- All three are available either by passing the behaviors to `on_retry`, or by calling the increasingly-verbosely-named `retry` (constant), `retry_with_backoff` (linear), or `retry_with_exponential_backoff` (exponential).
38
+ All three are available either by passing the behaviors to `on_retry`, or by calling the increasingly-verbosely-named `retry_constant` (constant), `retry_with_backoff` (linear), or `retry_with_exponential_backoff` (exponential). `retry` by itself *will not* actually retry anything, unless provided with an `on_retry` function, either per-call or in the relevant environment.
39
39
 
40
40
  Pester does log retry attempts (see below), however custom retry behavior that wraps existing `Behavior`s may be appropriate for logging custom information, incrementing statsd counters, etc. Also of note, different loggers can be passed per-call via the `logger` option.
41
41
 
@@ -51,7 +51,7 @@ Pester can be configured to be picky about what it chooses to retry and what it
51
51
 
52
52
  The first two are mutually-exclusive whitelist and blacklists, both taking either a single error class or an array. Raising an error not covered by `retry_error_classes` (whitelist) causes it to immediately fail:
53
53
 
54
- irb(main):002:0> Pester.retry(retry_error_classes: NotImplementedError) do
54
+ irb(main):002:0> Pester.retry_constant(retry_error_classes: NotImplementedError) do
55
55
  puts 'Trying...'
56
56
  fail 'derp'
57
57
  end
@@ -60,7 +60,7 @@ The first two are mutually-exclusive whitelist and blacklists, both taking eithe
60
60
 
61
61
  Raising an error covered by `reraise_error_classes` (blacklist) causes it to immediately fail:
62
62
 
63
- irb(main):002:0> Pester.retry(reraise_error_classes: NotImplementedError) do
63
+ irb(main):002:0> Pester.retry_constant(reraise_error_classes: NotImplementedError) do
64
64
  puts 'Trying...'
65
65
  raise NotImplementedError.new('derp')
66
66
  end
@@ -69,7 +69,7 @@ Raising an error covered by `reraise_error_classes` (blacklist) causes it to imm
69
69
 
70
70
  `retry_error_messages` also takes a single string or array, and calls `include?` on the error message. If it matches, the error's retried:
71
71
 
72
- irb(main):002:0> Pester.retry(retry_error_messages: 'please') do
72
+ irb(main):002:0> Pester.retry_constant(retry_error_messages: 'please') do
73
73
  puts 'Trying...'
74
74
  fail 'retry this, please'
75
75
  end
@@ -78,7 +78,7 @@ Raising an error covered by `reraise_error_classes` (blacklist) causes it to imm
78
78
 
79
79
  Because it calls `include?`, this also works for regexes:
80
80
 
81
- irb(main):002:0> Pester.retry(retry_error_messages: /\d/) do
81
+ irb(main):002:0> Pester.retry_constant(retry_error_messages: /\d/) do
82
82
  puts 'Trying...'
83
83
  fail 'retry this 2'
84
84
  end
@@ -92,8 +92,8 @@ Because it calls `include?`, this also works for regexes:
92
92
  The easiest way to coordinate sets of Pester options across an app is via environments--these are basically option hashes configured in Pester by name:
93
93
 
94
94
  Pester.configure do |c|
95
- c.environments[:aws] = { max_attempts: 3, delay_interval: 5 }
96
- c.environments[:internal] = { max_attempts: 2, delay_interval: 0 }
95
+ c.environments[:aws] = { max_attempts: 3, delay_interval: 5, on_retry: Pester::Behaviors::Sleep::Constant }
96
+ c.environments[:internal] = { max_attempts: 2, delay_interval: 0, on_retry: Pester::Behaviors::Sleep::Constant }
97
97
  end
98
98
 
99
99
  This will create two environments, `aws` and `internal`, which allow you to employ different backoff strategies, depending on the usage context. These are employed simply by calling `Pester.environment_name.retry` (where `retry` can also be another helper method):
@@ -112,7 +112,7 @@ This will create two environments, `aws` and `internal`, which allow you to empl
112
112
 
113
113
  Environments can also be merged with retry helper methods:
114
114
 
115
- Pester.aws.retry # acts different from
115
+ Pester.aws.retry_constant # acts different from
116
116
  Pester.aws.retry_with_exponential_backoff
117
117
 
118
118
  where the helper method's `Behavior` will take precedence.
@@ -127,7 +127,7 @@ Pester will write retry and exhaustion information into your logs, by default us
127
127
 
128
128
  And thus:
129
129
 
130
- irb(main):002:0> Pester.retry(delay_interval: 1) { puts 'Trying...'; fail 'derp' }
130
+ irb(main):002:0> Pester.retry_constant(delay_interval: 1) { puts 'Trying...'; fail 'derp' }
131
131
  Trying...
132
132
  Trying...
133
133
  Trying...
@@ -5,22 +5,27 @@ require 'pester/config'
5
5
  require 'pester/version'
6
6
 
7
7
  module Pester
8
- def self.configure(&block)
8
+ extend self
9
+ attr_accessor :environments
10
+
11
+ def configure(&block)
9
12
  Config.configure(&block)
10
- unless Config.environments.nil?
11
- self.environments = Hash[Config.environments.select { |_, e| e.is_a?(Hash) }.map { |k, e| [k.to_sym, Environment.new(e)] }]
12
- end
13
+
14
+ return if Config.environments.nil?
15
+
16
+ valid_environments = Config.environments.select { |_, e| e.is_a?(Hash) }
17
+ @environments = Hash[valid_environments.map { |k, e| [k.to_sym, Environment.new(e)] }]
13
18
  end
14
19
 
15
- def self.retry(options = {}, &block)
20
+ def retry_constant(options = {}, &block)
16
21
  retry_action(options.merge(on_retry: Behaviors::Sleep::Constant), &block)
17
22
  end
18
23
 
19
- def self.retry_with_backoff(options = {}, &block)
24
+ def retry_with_backoff(options = {}, &block)
20
25
  retry_action(options.merge(on_retry: Behaviors::Sleep::Linear), &block)
21
26
  end
22
27
 
23
- def self.retry_with_exponential_backoff(options = {}, &block)
28
+ def retry_with_exponential_backoff(options = {}, &block)
24
29
  retry_action({ delay_interval: 1 }.merge(options).merge(on_retry: Behaviors::Sleep::Exponential), &block)
25
30
  end
26
31
 
@@ -49,7 +54,7 @@ module Pester
49
54
  # FileUtils.rm_r(directory)
50
55
  # end
51
56
 
52
- def self.retry_action(opts = {}, &block)
57
+ def retry_action(opts = {}, &block)
53
58
  merge_defaults(opts)
54
59
  if opts[:retry_error_classes] && opts[:reraise_error_classes]
55
60
  fail 'You can only have one of retry_error_classes or reraise_error_classes'
@@ -79,25 +84,21 @@ module Pester
79
84
  nil
80
85
  end
81
86
 
82
- def respond_to?(method_sym)
87
+ def respond_to?(method_sym, options = {}, &block)
83
88
  super || Config.environments.key?(method_sym)
84
89
  end
85
90
 
86
- def method_missing(method_sym)
87
- if Config.environments.key?(method_sym)
88
- Config.environments[method_sym]
91
+ def method_missing(method_sym, options = {}, &block)
92
+ if @environments.key?(method_sym)
93
+ @environments[method_sym]
89
94
  else
90
95
  super
91
96
  end
92
97
  end
93
98
 
94
- class << self
95
- attr_accessor :environments
96
- end
97
-
98
99
  private
99
100
 
100
- def self.should_retry?(e, opts = {})
101
+ def should_retry?(e, opts = {})
101
102
  retry_error_classes = opts[:retry_error_classes]
102
103
  retry_error_messages = opts[:retry_error_messages]
103
104
  reraise_error_classes = opts[:reraise_error_classes]
@@ -117,7 +118,7 @@ module Pester
117
118
  end
118
119
  end
119
120
 
120
- def self.merge_defaults(opts)
121
+ def merge_defaults(opts)
121
122
  opts[:retry_error_classes] = opts[:retry_error_classes] ? Array(opts[:retry_error_classes]) : nil
122
123
  opts[:retry_error_messages] = opts[:retry_error_messages] ? Array(opts[:retry_error_messages]) : nil
123
124
  opts[:reraise_error_classes] = opts[:reraise_error_classes] ? Array(opts[:reraise_error_classes]) : nil
@@ -127,4 +128,6 @@ module Pester
127
128
  opts[:on_max_attempts_exceeded] ||= Behaviors::WarnAndReraise
128
129
  opts[:logger] ||= Config.logger
129
130
  end
131
+
132
+ alias_method :retry, :retry_action
130
133
  end
@@ -1,3 +1,3 @@
1
1
  module Pester
2
- VERSION = '0.2.0'
2
+ VERSION = '1.0.0'
3
3
  end
@@ -10,9 +10,9 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ['marc@lumoslabs.com']
11
11
  spec.summary = 'Common block-based retry for external calls.'
12
12
  spec.description = <<-EOD
13
- |We found ourselves constantly wrapping network-facing calls with all kinds of bespoke,
14
- | copied, and rewritten retry logic. This gem is an attempt to unify common behaviors,
15
- | like simple retry, retry with linear backoff, and retry with exponential backoff.
13
+ We found ourselves constantly wrapping network-facing calls with all kinds of bespoke,
14
+ copied, and rewritten retry logic. This gem is an attempt to unify common behaviors,
15
+ like simple retry, retry with linear backoff, and retry with exponential backoff.
16
16
  EOD
17
17
  spec.homepage = 'https://github.com/lumoslabs/pester'
18
18
  spec.license = 'MIT'
@@ -275,22 +275,25 @@ describe '#environments' do
275
275
  let(:environment_name) { :abc }
276
276
  let(:options) { { option: 1234 } }
277
277
 
278
- it 'adds it to the Pester environment list' do
278
+ before do
279
279
  Pester.configure do |config|
280
280
  config.environments[environment_name] = options
281
281
  end
282
+ end
282
283
 
284
+ it 'adds it to the Pester environment list' do
283
285
  expect(Pester.environments.count).to eq(1)
284
286
  end
285
287
 
286
288
  it 'contains an Environment with the appropriate options' do
287
- Pester.configure do |config|
288
- config.environments[environment_name] = options
289
- end
290
-
291
289
  expect(Pester.environments[environment_name].class).to eq(Pester::Environment)
292
290
  expect(Pester.environments[environment_name].options).to eq(options)
293
291
  end
292
+
293
+ it 'contains an Environment addressable directly from Pester with the appropriate options' do
294
+ expect(Pester.send(environment_name).class).to eq(Pester::Environment)
295
+ expect(Pester.send(environment_name).options).to eq(options)
296
+ end
294
297
  end
295
298
  end
296
299
 
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.2.0
4
+ version: 1.0.0
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-04-25 00:00:00.000000000 Z
11
+ date: 2015-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -53,9 +53,9 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.2'
55
55
  description: |2
56
- |We found ourselves constantly wrapping network-facing calls with all kinds of bespoke,
57
- | copied, and rewritten retry logic. This gem is an attempt to unify common behaviors,
58
- | like simple retry, retry with linear backoff, and retry with exponential backoff.
56
+ We found ourselves constantly wrapping network-facing calls with all kinds of bespoke,
57
+ copied, and rewritten retry logic. This gem is an attempt to unify common behaviors,
58
+ like simple retry, retry with linear backoff, and retry with exponential backoff.
59
59
  email:
60
60
  - marc@lumoslabs.com
61
61
  executables: []