iron_bank 2.0.2 → 2.1.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
- 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.