iron_bank 2.0.2 → 2.1.0

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
- SHA256:
3
- metadata.gz: 91fae8e035b3b2912c560e92f1082514e24fbf53a38ea9a3b2b64afd18a363fa
4
- data.tar.gz: 16a00f1540532b6f3c6473e8d7e66c18ef5acaed7754b3097957222db1aa27ba
2
+ SHA1:
3
+ metadata.gz: 901b217a92f89e748bd3e766c6d079ed15da7805
4
+ data.tar.gz: bacc2026bf92a9dceb35592c4c1306cac08cfaf5
5
5
  SHA512:
6
- metadata.gz: 1194bc5b7a1fc98a4aaa20b5060fa02bc9e58b43e40c87aa8bc67b7c7728ee312c796943c4eaf6e3981d19cbfe9fe682287e2beb35302ece13a2fe47eec12877
7
- data.tar.gz: 664e41aafd6c72aebb4930ff03e436fb9196bfc5439293cdb6d9aeb92426d7d71d23e66d05b2a4132d95fd6016ad30522b7be892e9ff2c5f07c7c16d572f40cf
6
+ metadata.gz: 592874e55ed11e85cdcb6877becf2b2d5635536414781c5c5e20e66d68859d5743b7a86559e8f962fdb5c29a96b219323e74af262dd54286a67fcecd584dd2af
7
+ data.tar.gz: 658224c2ae4b3f8ae18fea954a68d5ee73a05966d07d299a06985eec6599df655b58f9d325cf655ebbeac6d4af52bf60258512a7439b3211b5951aac99c4538c
data/.reek.yml CHANGED
@@ -64,9 +64,7 @@ detectors:
64
64
  - IronBank::Resources::ProductRatePlanChargeTier#self.load_records
65
65
 
66
66
  NilCheck:
67
- exclude:
68
- - IronBank::Local#load_records
69
- - IronBank::Resources::ProductRatePlanChargeTier#self.load_records
67
+ enabled: false
70
68
 
71
69
  TooManyInstanceVariables:
72
70
  max_instance_variables: 6
@@ -80,6 +78,7 @@ detectors:
80
78
  - IronBank::Client#connection
81
79
  - IronBank::Configuration#schema_directory=
82
80
  - IronBank::Configuration#initialize
81
+ - IronBank::Error#message_from_body
83
82
  - IronBank::Queryable#find_each
84
83
  - IronBank::Queryable#where
85
84
  - IronBank::Utils#camelize
data/iron_bank.gemspec CHANGED
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.require_paths = ['lib']
31
31
 
32
32
  spec.add_development_dependency 'bump', '~> 0.5'
33
- spec.add_development_dependency 'bundler', '~> 1.15'
33
+ spec.add_development_dependency 'bundler', '~> 2.0'
34
34
  spec.add_development_dependency 'dotenv', '~> 2.2'
35
35
  spec.add_development_dependency 'factory_bot', '~> 4.10'
36
36
  spec.add_development_dependency 'pry-byebug', '~> 3.4'
data/lib/iron_bank.rb CHANGED
@@ -58,7 +58,7 @@ require 'iron_bank/version'
58
58
  require 'iron_bank/csv'
59
59
  require 'iron_bank/error'
60
60
  require 'iron_bank/faraday_middleware/raise_error'
61
- require 'iron_bank/faraday_middleware/retriable_auth'
61
+ require 'iron_bank/faraday_middleware/renew_auth'
62
62
  require 'iron_bank/faraday_middleware'
63
63
 
64
64
  # Helpers
@@ -13,7 +13,7 @@ module IronBank
13
13
  def call
14
14
  @body = IronBank.client.connection.post(endpoint, params).body
15
15
 
16
- raise ::IronBank::UnprocessableEntity, errors unless success?
16
+ raise ::IronBank::UnprocessableEntityError, errors unless success?
17
17
 
18
18
  IronBank::Object.new(body).deep_underscore
19
19
  end
@@ -16,6 +16,12 @@ module IronBank
16
16
  #
17
17
  class InvalidHostname < Error; end
18
18
 
19
+ RETRIABLE_ERRORS = [
20
+ IronBank::LockCompetitionError,
21
+ IronBank::TemporaryError,
22
+ IronBank::UnauthorizedError
23
+ ].freeze
24
+
19
25
  # Alias each actions as a `Client` instance method
20
26
  IronBank::Actions.constants.each do |action|
21
27
  method_name = IronBank::Utils.underscore(action)
@@ -41,15 +47,27 @@ module IronBank
41
47
  validate_domain
42
48
  reset_connection if auth.expired?
43
49
 
50
+ retry_options = {
51
+ max: 4,
52
+ interval: 0.1,
53
+ interval_randomness: 0.05,
54
+ backoff_factor: 5,
55
+ exceptions: RETRIABLE_ERRORS,
56
+ retry_if: ->(_, ex) { RETRIABLE_ERRORS.include?(ex.class) }
57
+ }
58
+
44
59
  @connection ||= Faraday.new(faraday_config) do |conn|
45
- conn.use :ddtrace, open_tracing_options if open_tracing_enabled?
46
- conn.use instrumenter, instrumenter_options if instrumenter
47
60
  conn.request :json
48
- conn.request :retry, max: 2, exceptions: [IronBank::Unauthorized]
49
- conn.use :raise_error
50
- conn.request :retriable_auth, auth
61
+ conn.request :retry, retry_options
62
+
63
+ conn.response :raise_error
64
+ conn.response :renew_auth, auth
51
65
  conn.response :logger, IronBank.logger
52
66
  conn.response :json, content_type: /\bjson$/
67
+
68
+ conn.use :ddtrace, open_tracing_options if open_tracing_enabled?
69
+ conn.use instrumenter, instrumenter_options if instrumenter
70
+
53
71
  conn.adapter Faraday.default_adapter
54
72
  end
55
73
  end
@@ -6,24 +6,42 @@ module IronBank
6
6
  # Returns the appropriate IronBank::Error subclass based on status and
7
7
  # response message
8
8
  def self.from_response(response)
9
- status = response[:status].to_i
10
-
11
9
  klass = begin
12
- case status
13
- when 400 then IronBank::BadRequest
14
- when 401 then IronBank::Unauthorized
15
- when 404 then IronBank::NotFound
16
- when 422 then IronBank::UnprocessableEntity
17
- when 429 then IronBank::TooManyRequests
10
+ case response.status
11
+ when 200 then from_body(response)
12
+ when 400 then IronBank::BadRequestError
13
+ when 401 then IronBank::UnauthorizedError
14
+ when 404 then IronBank::NotFoundError
15
+ when 422 then IronBank::UnprocessableEntityError
16
+ when 429 then IronBank::TooManyRequestsError
18
17
  when 500 then IronBank::InternalServerError
19
18
  when 400..499 then IronBank::ClientError
20
19
  when 500..599 then IronBank::ServerError
20
+ else IronBank::Error
21
21
  end
22
22
  end
23
23
 
24
- return unless klass
24
+ klass&.new(response)
25
+ end
26
+
27
+ def self.from_body(response)
28
+ return unless (match = CODE_MATCHER.match(response.body.to_s))
29
+
30
+ CODE_CLASSES[match.captures.first]
31
+ end
32
+
33
+ attr_reader :response
34
+
35
+ def initialize(response = nil)
36
+ @response = response
37
+
38
+ message = response.is_a?(Faraday::Response) ? message_from_body : response
25
39
 
26
- klass.new(response)
40
+ super(message)
41
+ end
42
+
43
+ def message_from_body
44
+ response && "Body: #{response.body}"
27
45
  end
28
46
  end
29
47
 
@@ -31,23 +49,57 @@ module IronBank
31
49
  class ClientError < Error; end
32
50
 
33
51
  # Raised when Zuora returns a 400 HTTP status code
34
- class BadRequest < ClientError; end
52
+ class BadRequestError < ClientError; end
35
53
 
36
54
  # Raised when Zuora returns a 401 HTTP status code
37
- class Unauthorized < Error; end
55
+ class UnauthorizedError < ClientError; end
38
56
 
39
57
  # Raised when Zuora returns a 404 HTTP status code
40
- class NotFound < ClientError; end
58
+ class NotFoundError < ClientError; end
59
+
60
+ # Zuora doesn't return a 409, but indicates it via the response
61
+ class ConflictError < ClientError; end
41
62
 
42
63
  # Raised when Zuora return 422 and unsuccessful action responses
43
- class UnprocessableEntity < Error; end
64
+ class UnprocessableEntityError < ClientError; end
44
65
 
45
66
  # Raised when Zuora returns a 429 HTTP status code
46
- class TooManyRequests < ClientError; end
67
+ class TooManyRequestsError < ClientError; end
47
68
 
48
69
  # Raised on errors in the 500-599 range
49
70
  class ServerError < Error; end
50
71
 
51
72
  # Raised when Zuora returns a 500 HTTP status code
52
73
  class InternalServerError < ServerError; end
74
+
75
+ # Zuora doesn't return a 502, but indicates it via the response
76
+ class BadGatewayError < ServerError; end
77
+
78
+ # Zuora indicates a temporary error via the response
79
+ class TemporaryError < ServerError; end
80
+
81
+ # Zuora indicates lock competition errors via the response
82
+ class LockCompetitionError < TemporaryError; end
83
+
84
+ CODE_CLASSES = {
85
+ 'API_DISABLED' => ServerError,
86
+ 'CANNOT_DELETE' => UnprocessableEntityError,
87
+ 'DUPLICATE_VALUE' => ConflictError,
88
+ 'INVALID_FIELD' => BadRequestError,
89
+ 'INVALID_ID' => BadRequestError,
90
+ 'INVALID_TYPE' => BadRequestError,
91
+ 'INVALID_VALUE' => BadRequestError,
92
+ 'LOCK_COMPETITION' => LockCompetitionError,
93
+ 'MALFORMED_QUERY' => ClientError,
94
+ 'MISSING_REQUIRED_VALUE' => ClientError,
95
+ 'REQUEST_EXCEEDED_LIMIT' => TooManyRequestsError,
96
+ 'REQUEST_EXCEEDED_RATE' => TooManyRequestsError,
97
+ 'TEMPORARY_ERROR' => TemporaryError,
98
+ 'TRANSACTION_FAILED' => InternalServerError,
99
+ 'TRANSACTION_TERMINATED' => InternalServerError,
100
+ 'TRANSACTION_TIMEOUT' => BadGatewayError,
101
+ 'UNKNOWN_ERROR' => InternalServerError
102
+ }.freeze
103
+
104
+ CODE_MATCHER = /(#{CODE_CLASSES.keys.join('|')})/.freeze
53
105
  end
@@ -4,12 +4,11 @@
4
4
  module IronBank
5
5
  # IronBank Faraday middleware module
6
6
  module FaradayMiddleware
7
- if Faraday::Middleware.respond_to? :register_middleware
8
- Faraday::Middleware.register_middleware \
9
- raise_error: -> { RaiseError }
10
-
11
- Faraday::Request.register_middleware \
12
- retriable_auth: -> { RetriableAuth }
7
+ if Faraday::Middleware.respond_to?(:register_middleware)
8
+ Faraday::Response.register_middleware(
9
+ raise_error: -> { RaiseError },
10
+ renew_auth: -> { RenewAuth }
11
+ )
13
12
  end
14
13
  end
15
14
  end
@@ -9,8 +9,8 @@ module IronBank
9
9
  class RaiseError < Faraday::Response::Middleware
10
10
  private
11
11
 
12
- def on_complete(response)
13
- (error = IronBank::Error.from_response(response)) && raise(error)
12
+ def on_complete(env)
13
+ (error = IronBank::Error.from_response(env.response)) && raise(error)
14
14
  end
15
15
  end
16
16
  end
@@ -5,17 +5,17 @@ module IronBank
5
5
  # IronBank Faraday middleware module
6
6
  module FaradayMiddleware
7
7
  # This middleware reauthorize the request on unauthorized request
8
- class RetriableAuth < Faraday::Middleware
8
+ class RenewAuth < Faraday::Response::Middleware
9
9
  def initialize(app, auth)
10
10
  @auth = auth
11
+
11
12
  super(app)
12
13
  end
13
14
 
14
- def call(env)
15
+ def on_complete(env)
15
16
  @env = env
16
- renew_auth_header if env.status == 401
17
17
 
18
- @app.call(env)
18
+ renew_auth_header if env.status == 401
19
19
  end
20
20
 
21
21
  private
@@ -6,7 +6,7 @@ module IronBank
6
6
  module Queryable
7
7
  # We use the REST endpoint for the `find` method
8
8
  def find(id)
9
- raise IronBank::NotFound unless id
9
+ raise IronBank::NotFoundError unless id
10
10
 
11
11
  response = IronBank.client.connection.get(
12
12
  "v1/object/#{object_name}/#{id}"
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module IronBank
4
- VERSION = '2.0.2'
4
+ VERSION = '2.1.0'
5
5
  API_VERSION = 'v1'
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iron_bank
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mickael Pham
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2019-01-03 00:00:00.000000000 Z
14
+ date: 2019-03-19 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bump
@@ -33,14 +33,14 @@ dependencies:
33
33
  requirements:
34
34
  - - "~>"
35
35
  - !ruby/object:Gem::Version
36
- version: '1.15'
36
+ version: '2.0'
37
37
  type: :development
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
40
40
  requirements:
41
41
  - - "~>"
42
42
  - !ruby/object:Gem::Version
43
- version: '1.15'
43
+ version: '2.0'
44
44
  - !ruby/object:Gem::Dependency
45
45
  name: dotenv
46
46
  requirement: !ruby/object:Gem::Requirement
@@ -321,7 +321,7 @@ files:
321
321
  - lib/iron_bank/error.rb
322
322
  - lib/iron_bank/faraday_middleware.rb
323
323
  - lib/iron_bank/faraday_middleware/raise_error.rb
324
- - lib/iron_bank/faraday_middleware/retriable_auth.rb
324
+ - lib/iron_bank/faraday_middleware/renew_auth.rb
325
325
  - lib/iron_bank/instrumentation.rb
326
326
  - lib/iron_bank/local.rb
327
327
  - lib/iron_bank/local_records.rb
@@ -380,7 +380,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
380
380
  version: '0'
381
381
  requirements: []
382
382
  rubyforge_project:
383
- rubygems_version: 2.7.6
383
+ rubygems_version: 2.6.14.3
384
384
  signing_key:
385
385
  specification_version: 4
386
386
  summary: An opinionated Ruby interface to the Zuora API.