ridley 2.5.1 → 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7015d6698dd19c93412740e2ff16f5432025e0ef
4
- data.tar.gz: 98f72e264ea4832ab085c887e71a001dad03ca35
3
+ metadata.gz: 507254a6cdf340a5c7e11ac8354043df5f66d5cf
4
+ data.tar.gz: bdea7bdd458295e87a7401968cba749a7aa8e738
5
5
  SHA512:
6
- metadata.gz: 6513631b259a1909e6624c101b0cf2f64757992b754f8dfb51514e606aefacb6b28ba8720491f457daaccfc81a8f2288cb72e3249fc3470247bfda2412176b2e
7
- data.tar.gz: e7a519e2bd14c9ed26be2bf9981e5d44003268589f8e3976ee4552af5d412f34a7d22d5a33e24871919720214fa64c9c71d54714db3ec3096215ee69d09a7e33
6
+ metadata.gz: a8f65480cb316c3b5ab316fa68687582a15014042003ed0d85a684af38aea0f10a83a39fb2fcb0514adfcaa7a41e18b9aff317a1fdf6390970ffea118389afd0
7
+ data.tar.gz: a9c3c56283f0873eaacee0fd5fbf6a9b9f09100886b704da43d83b96d9ebc6254665021c6516304adf02c5506dc5672247a25e0bfa1384e1130946340272daf6
@@ -18,8 +18,6 @@ module Ridley::Chef
18
18
 
19
19
  if ignore
20
20
  log.debug "Using '#{FILENAME}' at '#{ignore}'"
21
- else
22
- log.debug "Could not find '#{FILENAME}' at '#{path}'"
23
21
  end
24
22
 
25
23
  super(ignore, base: path)
@@ -239,8 +239,6 @@ module Ridley::Chef
239
239
  version = version_args.first
240
240
  @platforms[platform] = Solve::Constraint.new(version).to_s
241
241
  @platforms[platform]
242
- rescue Solve::Errors::InvalidConstraintFormat => ex
243
- raise InvalidVersionConstraint, ex.to_s
244
242
  end
245
243
 
246
244
  # Adds a dependency on another cookbook, with version checking strings.
@@ -257,8 +255,6 @@ module Ridley::Chef
257
255
  version = version_args.first
258
256
  @dependencies[cookbook] = Solve::Constraint.new(version).to_s
259
257
  @dependencies[cookbook]
260
- rescue Solve::Errors::InvalidConstraintFormat => ex
261
- raise InvalidVersionConstraint, ex.to_s
262
258
  end
263
259
 
264
260
  # Adds a recommendation for another cookbook, with version checking strings.
@@ -275,8 +271,6 @@ module Ridley::Chef
275
271
  version = version_args.first
276
272
  @recommendations[cookbook] = Solve::Constraint.new(version).to_s
277
273
  @recommendations[cookbook]
278
- rescue Solve::Errors::InvalidConstraintFormat => ex
279
- raise InvalidVersionConstraint, ex.to_s
280
274
  end
281
275
 
282
276
  # Adds a suggestion for another cookbook, with version checking strings.
@@ -293,8 +287,6 @@ module Ridley::Chef
293
287
  version = version_args.first
294
288
  @suggestions[cookbook] = Solve::Constraint.new(version).to_s
295
289
  @suggestions[cookbook]
296
- rescue Solve::Errors::InvalidConstraintFormat => ex
297
- raise InvalidVersionConstraint, ex.to_s
298
290
  end
299
291
 
300
292
  # Adds a conflict for another cookbook, with version checking strings.
@@ -311,8 +303,6 @@ module Ridley::Chef
311
303
  version = version_args.first
312
304
  @conflicting[cookbook] = Solve::Constraint.new(version).to_s
313
305
  @conflicting[cookbook]
314
- rescue Solve::Errors::InvalidConstraintFormat => ex
315
- raise InvalidVersionConstraint, ex.to_s
316
306
  end
317
307
 
318
308
  # Adds a recipe, definition, or resource provided by this cookbook.
@@ -333,8 +323,6 @@ module Ridley::Chef
333
323
  version = version_args.first
334
324
  @providing[cookbook] = Solve::Constraint.new(version).to_s
335
325
  @providing[cookbook]
336
- rescue Solve::Errors::InvalidConstraintFormat => ex
337
- raise InvalidVersionConstraint, ex.to_s
338
326
  end
339
327
 
340
328
  # Adds a cookbook that is replaced by this one, with version checking strings.
@@ -350,8 +338,6 @@ module Ridley::Chef
350
338
  version = version_args.first
351
339
  @replacing[cookbook] = Solve::Constraint.new(version).to_s
352
340
  @replacing[cookbook]
353
- rescue Solve::Errors::InvalidConstraintFormat => ex
354
- raise InvalidVersionConstraint, ex.to_s
355
341
  end
356
342
 
357
343
  # Adds a description for a recipe.
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  module Ridley::Chef
2
4
  class Cookbook
3
5
  require_relative 'cookbook/metadata'
@@ -24,24 +26,24 @@ module Ridley::Chef
24
26
  # @param [#to_s] path
25
27
  # a path on disk to the location of a Cookbook
26
28
  #
27
- # @option options [String] :name
28
- # explicitly supply the name of the cookbook we are loading. This is useful if
29
- # you are dealing with a cookbook that does not have well-formed metadata
30
- #
31
29
  # @raise [IOError] if the path does not contain a metadata.rb or metadata.json file
32
30
  #
33
31
  # @return [Ridley::Chef::Cookbook]
34
- def from_path(path, options = {})
35
- path = Pathname.new(path)
36
- metadata = if (metadata_file = path.join(Metadata::COMPILED_FILE_NAME)).exist?
37
- Cookbook::Metadata.from_json(File.read(metadata_file))
38
- elsif (metadata_file = path.join(Metadata::RAW_FILE_NAME)).exist?
39
- Cookbook::Metadata.from_file(metadata_file)
32
+ def from_path(path)
33
+ path = Pathname.new(path)
34
+
35
+ if (file = path.join(Metadata::COMPILED_FILE_NAME)).exist?
36
+ metadata = Metadata.from_json(File.read(file))
37
+ elsif (file = path.join(Metadata::RAW_FILE_NAME)).exist?
38
+ metadata = Metadata.from_file(file)
40
39
  else
41
40
  raise IOError, "no #{Metadata::COMPILED_FILE_NAME} or #{Metadata::RAW_FILE_NAME} found at #{path}"
42
41
  end
43
42
 
44
- metadata.name(options[:name].presence || metadata.name.presence || File.basename(path))
43
+ unless metadata.name.presence
44
+ raise Ridley::Errors::MissingNameAttribute.new(path)
45
+ end
46
+
45
47
  new(metadata.name, path, metadata)
46
48
  end
47
49
  end
data/lib/ridley/client.rb CHANGED
@@ -140,7 +140,7 @@ module Ridley
140
140
  @options[:client_key] = File.expand_path(@options[:client_key])
141
141
  raise Errors::ClientKeyFileNotFoundOrInvalid, "client key is invalid or not found at: '#{@options[:client_key]}'" unless File.exist?(@options[:client_key]) && verify_client_key(::IO.read(@options[:client_key]))
142
142
  end
143
-
143
+
144
144
  @connection_registry = Celluloid::Registry.new
145
145
  @resources_registry = Celluloid::Registry.new
146
146
  @connection_supervisor = ConnectionSupervisor.new(@connection_registry, @options)
@@ -276,8 +276,8 @@ module Ridley
276
276
  end
277
277
 
278
278
  def finalize_callback
279
- @connection_supervisor.terminate if @connection_supervisor && @connection_supervisor.alive?
280
- @resources_supervisor.terminate if @resources_supervisor && @resources_supervisor.alive?
279
+ @connection_supervisor.async.terminate if @connection_supervisor
280
+ @resources_supervisor.async.terminate if @resources_supervisor
281
281
  end
282
282
  end
283
283
  end
@@ -44,10 +44,10 @@ module Ridley
44
44
  options = options.reverse_merge(retries: 5, retry_interval: 0.5)
45
45
  @client_name = client_name
46
46
  @client_key = client_key
47
- @retries = options[:retries]
48
- @retry_interval = options[:retry_interval]
47
+ @retries = options.delete(:retries)
48
+ @retry_interval = options.delete(:retry_interval)
49
49
 
50
- options[:builder] = Faraday::Builder.new do |b|
50
+ options[:builder] = Faraday::RackBuilder.new do |b|
51
51
  b.request :retry,
52
52
  max: @retries,
53
53
  interval: @retry_interval,
data/lib/ridley/errors.rb CHANGED
@@ -42,6 +42,29 @@ module Ridley
42
42
  "no encrypted data bag secret was set for this Ridley connection"
43
43
  end
44
44
  end
45
+ class FromFileParserError < RidleyError
46
+ def initialize(filename, error)
47
+ super "Could not parse `#{filename}': #{error.message}"
48
+
49
+ # Populate the backtrace with the actual error though
50
+ set_backtrace(error.backtrace)
51
+ end
52
+ end
53
+
54
+ class MissingNameAttribute < RidleyError
55
+ def initialize(path)
56
+ @path = path
57
+ end
58
+
59
+ def to_s
60
+ out = "The metadata at '#{@path}' does not contain a 'name' "
61
+ out << "attribute. While Chef does not strictly enforce this "
62
+ out << "requirement, Ridley cannot continue without a valid metadata "
63
+ out << "'name' entry."
64
+ out
65
+ end
66
+ alias_method :message, :to_s
67
+ end
45
68
 
46
69
  class BootstrapError < RidleyError; end
47
70
  class ClientKeyFileNotFoundOrInvalid < BootstrapError; end
@@ -3,7 +3,6 @@ require 'logger'
3
3
  module Ridley
4
4
  module Logging
5
5
  class << self
6
-
7
6
  # @return [Logger]
8
7
  def logger
9
8
  @logger ||= begin
@@ -87,4 +87,4 @@ module Ridley
87
87
  end
88
88
  end
89
89
 
90
- Faraday.register_middleware(:request, chef_auth: Ridley::Middleware::ChefAuth)
90
+ Faraday::Request.register_middleware chef_auth: Ridley::Middleware::ChefAuth
@@ -28,4 +28,4 @@ module Ridley
28
28
  end
29
29
  end
30
30
 
31
- Faraday.register_middleware(:response, chef_response: Ridley::Middleware::ChefResponse)
31
+ Faraday::Response.register_middleware chef_response: Ridley::Middleware::ChefResponse
@@ -132,4 +132,4 @@ module Ridley
132
132
  end
133
133
  end
134
134
 
135
- Faraday.register_middleware(:response, follow_redirects: Ridley::Middleware::FollowRedirects)
135
+ Faraday::Response.register_middleware follow_redirects: Ridley::Middleware::FollowRedirects
@@ -15,4 +15,4 @@ module Ridley
15
15
  end
16
16
  end
17
17
 
18
- Faraday.register_middleware(:response, gzip: Ridley::Middleware::Gzip)
18
+ Faraday::Response.register_middleware gzip: Ridley::Middleware::Gzip
@@ -106,4 +106,4 @@ module Ridley
106
106
  end
107
107
  end
108
108
 
109
- Faraday.register_middleware(:response, parse_json: Ridley::Middleware::ParseJson)
109
+ Faraday::Response.register_middleware parse_json: Ridley::Middleware::ParseJson
@@ -25,11 +25,11 @@ module Ridley::Mixin
25
25
  def from_file(filename)
26
26
  filename = filename.to_s
27
27
 
28
- if File.exists?(filename) && File.readable?(filename)
28
+ ensure_presence!(filename)
29
+
30
+ with_error_handling(filename) do
29
31
  self.instance_eval(IO.read(filename), filename, 1)
30
32
  self
31
- else
32
- raise IOError, "Could not open or read: '#{filename}'"
33
33
  end
34
34
  end
35
35
 
@@ -42,12 +42,38 @@ module Ridley::Mixin
42
42
  def class_from_file(filename)
43
43
  filename = filename.to_s
44
44
 
45
- if File.exists?(filename) && File.readable?(filename)
45
+ ensure_presence!(filename)
46
+
47
+ with_error_handling(filename) do
46
48
  self.class_eval(IO.read(filename), filename, 1)
47
49
  self
48
- else
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ # Ensure the given filename and path is readable
56
+ #
57
+ # @param [String] filename
58
+ #
59
+ # @raise [IOError]
60
+ # if the target file does not exist or is not readable
61
+ def ensure_presence!(filename)
62
+ unless File.exists?(filename) && File.readable?(filename)
49
63
  raise IOError, "Could not open or read: '#{filename}'"
50
64
  end
51
65
  end
66
+
67
+ # Execute the given block, handling any exceptions that occur
68
+ #
69
+ # @param [String] filename
70
+ #
71
+ # @raise [Ridley::Errors::FromFileParserError]
72
+ # if any exceptions if raised
73
+ def with_error_handling(filename)
74
+ yield
75
+ rescue => e
76
+ raise Ridley::Errors::FromFileParserError.new(filename, e)
77
+ end
52
78
  end
53
79
  end
@@ -171,10 +171,6 @@ module Ridley
171
171
  # @param [String] path
172
172
  # path to a cookbook on local disk
173
173
  #
174
- # @option options [String] :name
175
- # automatically populated by the metadata of the cookbook at the given path, but
176
- # in the event that the metadata does not contain a name it can be specified with
177
- # this option
178
174
  # @option options [Boolean] :force (false)
179
175
  # Upload the Cookbook even if the version already exists and is frozen on
180
176
  # the target Chef Server
@@ -187,7 +183,7 @@ module Ridley
187
183
  # @return [Hash]
188
184
  def upload(path, options = {})
189
185
  options = options.reverse_merge(validate: true, force: false, freeze: false)
190
- cookbook = Ridley::Chef::Cookbook.from_path(path, options.slice(:name))
186
+ cookbook = Ridley::Chef::Cookbook.from_path(path)
191
187
 
192
188
  unless (existing = find(cookbook.cookbook_name, cookbook.version)).nil?
193
189
  if existing.frozen? && options[:force] == false
@@ -31,7 +31,7 @@ module Ridley
31
31
  private
32
32
 
33
33
  def finalize_callback
34
- item_resource.terminate if item_resource && item_resource.alive?
34
+ item_resource.async.terminate if item_resource
35
35
  end
36
36
  end
37
37
  end
@@ -8,7 +8,7 @@ module Ridley
8
8
  def initialize(connection_registry, client_name, client_key, options = {})
9
9
  super(connection_registry)
10
10
  options = options.reverse_merge(pool_size: 4)
11
- @uploader = SandboxUploader.pool(size: options[:pool_size], args: [ client_name, client_key, options ])
11
+ @uploader = SandboxUploader.pool(size: options.delete(:pool_size), args: [ client_name, client_key, options ])
12
12
  end
13
13
 
14
14
  # Create a new Sandbox on the client's Chef Server. A Sandbox requires an
@@ -98,7 +98,7 @@ module Ridley
98
98
  attr_reader :uploader
99
99
 
100
100
  def finalize_callback
101
- uploader.terminate if uploader && uploader.alive?
101
+ uploader.async.terminate if uploader
102
102
  end
103
103
  end
104
104
  end
@@ -1,3 +1,3 @@
1
1
  module Ridley
2
- VERSION = "2.5.1"
2
+ VERSION = "3.0.0.rc1"
3
3
  end
data/ridley.gemspec CHANGED
@@ -23,10 +23,10 @@ Gem::Specification.new do |s|
23
23
  s.add_dependency 'buff-extensions', '~> 0.3'
24
24
  s.add_dependency 'buff-ignore', '~> 1.1'
25
25
  s.add_dependency 'buff-shell_out', '~> 0.1'
26
- s.add_dependency 'celluloid', '~> 0.15'
27
- s.add_dependency 'celluloid-io', '~> 0.15'
26
+ s.add_dependency 'celluloid', '~> 0.16.0.pre'
27
+ s.add_dependency 'celluloid-io', '~> 0.16.0.pre'
28
28
  s.add_dependency 'erubis'
29
- s.add_dependency 'faraday', '~> 0.8.4'
29
+ s.add_dependency 'faraday', '~> 0.9.0'
30
30
  s.add_dependency 'hashie', '>= 2.0.2'
31
31
  s.add_dependency 'json', '>= 1.7.7'
32
32
  s.add_dependency 'mixlib-authentication', '>= 1.3.0'
@@ -1,5 +1,5 @@
1
1
  RSpec.configuration.before(:each) do
2
- class Celluloid::ActorProxy
2
+ class Celluloid::CellProxy
3
3
  unless @rspec_compatible
4
4
  @rspec_compatible = true
5
5
  undef_method :should_receive if method_defined?(:should_receive)
@@ -15,10 +15,6 @@ describe Ridley::Chef::Cookbook do
15
15
  subject.from_path(cookbook_path).cookbook_name.should eql("example_cookbook")
16
16
  end
17
17
 
18
- it "sets the cookbook_name attribute to the value of the :name option if given" do
19
- subject.from_path(cookbook_path, name: "rspec_tester").cookbook_name.should eql("rspec_tester")
20
- end
21
-
22
18
  context "given a path that does not contain a metadata file" do
23
19
  it "raises an IOError" do
24
20
  lambda {
@@ -35,8 +31,10 @@ describe Ridley::Chef::Cookbook do
35
31
  FileUtils.touch(File.join(cookbook_path, 'metadata.rb'))
36
32
  end
37
33
 
38
- it "sets the name of the cookbook to the name of the directory containing it" do
39
- subject.from_path(cookbook_path).cookbook_name.should eql("directory_name")
34
+ it "raises an exception" do
35
+ expect {
36
+ subject.from_path(cookbook_path)
37
+ }.to raise_error(Ridley::Errors::MissingNameAttribute)
40
38
  end
41
39
  end
42
40
 
@@ -158,7 +156,14 @@ describe Ridley::Chef::Cookbook do
158
156
  end
159
157
 
160
158
  context "when a metadata.json file is not present" do
161
- before { FileUtils.rm_f(File.join(cookbook_path, "metadata.json")) }
159
+ before do
160
+ FileUtils.rm_f(File.join(cookbook_path, 'metadata.json'))
161
+
162
+ File.open(File.join(cookbook_path, 'metadata.rb'), 'w+') do |f|
163
+ f.write "name 'cookbook'"
164
+ end
165
+ end
166
+
162
167
  its(:compiled_metadata?) { should be_false }
163
168
  end
164
169
  end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ module Ridley
4
+ describe Mixin::FromFile do
5
+ describe '.from_file' do
6
+ context 'when there is bad Ruby in the file' do
7
+ let(:instance) { Class.new { include Ridley::Mixin::FromFile }.new }
8
+
9
+ before do
10
+ File.stub(:exists?).and_return(true)
11
+ File.stub(:readable?).and_return(true)
12
+ IO.stub(:read).and_return('invalid Ruby code')
13
+ end
14
+
15
+ it 'raises a FromFileParserError' do
16
+ expect {
17
+ instance.from_file('/path')
18
+ }.to raise_error(Errors::FromFileParserError)
19
+ end
20
+
21
+ it 'includes the backtrace from the original error' do
22
+ expect { instance.from_file('/path') }.to raise_error { |error|
23
+ expect(error.message).to include("undefined local variable or method `code' for")
24
+ expect(error.backtrace).to include("/path:1:in `block in from_file'")
25
+ }
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ridley
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.1
4
+ version: 3.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jamie Winsor
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-02-17 00:00:00.000000000 Z
12
+ date: 2014-04-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: addressable
@@ -101,28 +101,28 @@ dependencies:
101
101
  requirements:
102
102
  - - ~>
103
103
  - !ruby/object:Gem::Version
104
- version: '0.15'
104
+ version: 0.16.0.pre
105
105
  type: :runtime
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
109
  - - ~>
110
110
  - !ruby/object:Gem::Version
111
- version: '0.15'
111
+ version: 0.16.0.pre
112
112
  - !ruby/object:Gem::Dependency
113
113
  name: celluloid-io
114
114
  requirement: !ruby/object:Gem::Requirement
115
115
  requirements:
116
116
  - - ~>
117
117
  - !ruby/object:Gem::Version
118
- version: '0.15'
118
+ version: 0.16.0.pre
119
119
  type: :runtime
120
120
  prerelease: false
121
121
  version_requirements: !ruby/object:Gem::Requirement
122
122
  requirements:
123
123
  - - ~>
124
124
  - !ruby/object:Gem::Version
125
- version: '0.15'
125
+ version: 0.16.0.pre
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: erubis
128
128
  requirement: !ruby/object:Gem::Requirement
@@ -143,14 +143,14 @@ dependencies:
143
143
  requirements:
144
144
  - - ~>
145
145
  - !ruby/object:Gem::Version
146
- version: 0.8.4
146
+ version: 0.9.0
147
147
  type: :runtime
148
148
  prerelease: false
149
149
  version_requirements: !ruby/object:Gem::Requirement
150
150
  requirements:
151
151
  - - ~>
152
152
  - !ruby/object:Gem::Version
153
- version: 0.8.4
153
+ version: 0.9.0
154
154
  - !ruby/object:Gem::Dependency
155
155
  name: hashie
156
156
  requirement: !ruby/object:Gem::Requirement
@@ -304,7 +304,6 @@ files:
304
304
  - lib/ridley/middleware/follow_redirects.rb
305
305
  - lib/ridley/middleware/gzip.rb
306
306
  - lib/ridley/middleware/parse_json.rb
307
- - lib/ridley/middleware/retry.rb
308
307
  - lib/ridley/mixin.rb
309
308
  - lib/ridley/mixin/checksum.rb
310
309
  - lib/ridley/mixin/from_file.rb
@@ -388,6 +387,7 @@ files:
388
387
  - spec/unit/ridley/middleware/chef_response_spec.rb
389
388
  - spec/unit/ridley/middleware/gzip_spec.rb
390
389
  - spec/unit/ridley/middleware/parse_json_spec.rb
390
+ - spec/unit/ridley/mixins/from_file_spec.rb
391
391
  - spec/unit/ridley/resource_spec.rb
392
392
  - spec/unit/ridley/resources/client_resource_spec.rb
393
393
  - spec/unit/ridley/resources/cookbook_resource_spec.rb
@@ -416,9 +416,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
416
416
  version: 1.9.1
417
417
  required_rubygems_version: !ruby/object:Gem::Requirement
418
418
  requirements:
419
- - - '>='
419
+ - - '>'
420
420
  - !ruby/object:Gem::Version
421
- version: '0'
421
+ version: 1.3.1
422
422
  requirements: []
423
423
  rubyforge_project:
424
424
  rubygems_version: 2.0.14
@@ -488,6 +488,7 @@ test_files:
488
488
  - spec/unit/ridley/middleware/chef_response_spec.rb
489
489
  - spec/unit/ridley/middleware/gzip_spec.rb
490
490
  - spec/unit/ridley/middleware/parse_json_spec.rb
491
+ - spec/unit/ridley/mixins/from_file_spec.rb
491
492
  - spec/unit/ridley/resource_spec.rb
492
493
  - spec/unit/ridley/resources/client_resource_spec.rb
493
494
  - spec/unit/ridley/resources/cookbook_resource_spec.rb
@@ -1,60 +0,0 @@
1
- module Ridley
2
- # Catches exceptions and retries each request a limited number of times.
3
- #
4
- # @example
5
- #
6
- # Faraday.new do |conn|
7
- # conn.request :retry, max: 2, interval: 0.05, exceptions: [CustomException, Faraday::Timeout::Error]
8
- # conn.adapter ...
9
- # end
10
- #
11
- # @note Borrowed and modified from: {https://github.com/lostisland/faraday/blob/master/lib/faraday/request/retry.rb}
12
- # use the Faraday official middleware after the release of 0.9.x
13
- class Middleware::Retry < Faraday::Middleware
14
- # @option options [Integer] :max
15
- # maximum number of retries
16
- # @option options [Float] :interval
17
- # pause in seconds between retries
18
- # @option options [Array] :exceptions
19
- # the list of exceptions to handle
20
- def initialize(app, options = {})
21
- super(app)
22
- @options = options.slice(:max, :interval, :exceptions)
23
- @errmatch = build_exception_matcher(@options[:exceptions])
24
- end
25
-
26
- def call(env)
27
- retries = @options[:max]
28
- begin
29
- @app.call(env)
30
- rescue @errmatch
31
- if retries > 0
32
- retries -= 1
33
- sleep @options[:interval] if @options[:interval] > 0
34
- retry
35
- end
36
- raise
37
- end
38
- end
39
-
40
- # construct an exception matcher object.
41
- #
42
- # An exception matcher for the rescue clause can usually be any object that
43
- # responds to `===`, but for Ruby 1.8 it has to be a Class or Module.
44
- def build_exception_matcher(exceptions)
45
- matcher = Module.new
46
- (class << matcher; self; end).class_eval do
47
- define_method(:===) do |error|
48
- exceptions.any? do |ex|
49
- if ex.is_a? Module then error.is_a? ex
50
- else error.class.to_s == ex.to_s
51
- end
52
- end
53
- end
54
- end
55
- matcher
56
- end
57
- end
58
- end
59
-
60
- Faraday.register_middleware(:request, retry: Ridley::Middleware::Retry)