erp_integration 0.56.0 → 0.58.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
  SHA256:
3
- metadata.gz: 55974d4e2c7b76ca461070fe996522e0b7fa06391760549f8959000ed07b2a9e
4
- data.tar.gz: 43683efd68525709be0fcba1537051830f52d7c0663779a7ab5b4c24b0a6e2e9
3
+ metadata.gz: 0414ab9ad823ea6eb9770829c73ec69f09776fc9cd9983ebd09cbd1efba44320
4
+ data.tar.gz: 8943d4e6c2868dd5d158e9a48af258b2cb8193f38715153aea55bca6d7cdeb74
5
5
  SHA512:
6
- metadata.gz: f0943cc3b1047ef17259a1eeb039fdd65ee74cb3ebc6911ff431162f60058b89d8e26e3f742028b261c2979c304aab4b1a0fd155e5d72fd0f0063a3a3afa351f
7
- data.tar.gz: 4a06481fb232e9ad506c0d038af4114169546d622eecec0e6d5b03877e6f85648777c278728f87f6cae52c3e695f382ec34e4c1a2adcfadf0d9af23fc354374f
6
+ metadata.gz: feefbf3f9aa3900e9f4b6e2c2662199e1850211880ab50c2157312b562e5af4152e4545f61712d70ccdefb47f3b48c617663d6b2977a5bd613efa6f20842868c
7
+ data.tar.gz: c901363ad8f2cbf5e014a4e3fb1236b71e9c1d24762c710f90e3d2c4802bfaeb3f8144b7f22e17ca44e6d0bb9aaed0b0ce77082d30843d74f16bd4f2372c0c0c
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.2.2
1
+ 3.0.2
@@ -168,10 +168,6 @@ module ErpIntegration
168
168
  # @return [Symbol] The configured adapter for the tracking number.
169
169
  attr_writer :product_option_adapter
170
170
 
171
- # Logger that will be used for HTTP operations on Client
172
- # @return [Logger] The configured logger
173
- attr_accessor :logger
174
-
175
171
  def initialize(**options)
176
172
  options.each_pair do |key, value|
177
173
  public_send("#{key}=", value) if respond_to?("#{key}=")
@@ -321,6 +317,14 @@ module ErpIntegration
321
317
  def rate_limiters=(rate_limiters)
322
318
  @rate_limiters = (rate_limiters || []).each { |limiter| RateLimiter.validate!(limiter) }
323
319
  end
320
+
321
+ def logger
322
+ @logger || Logger.new(nil)
323
+ end
324
+
325
+ def logger=(logger)
326
+ @logger = Logger.new(logger)
327
+ end
324
328
  end
325
329
 
326
330
  # Returns ERP Integration's configuration.
@@ -32,7 +32,7 @@ module ErpIntegration
32
32
  class MethodNotAllowed < HttpError; end
33
33
  class NotAccepted < HttpError; end
34
34
  class UnprocessableEntity < HttpError; end
35
- class TooManyRequests < HttpError; end
35
+ class TooManyRequests < Faraday::Error; end
36
36
  class InternalServerError < HttpError; end
37
37
  end
38
38
  end
@@ -3,6 +3,8 @@
3
3
  module ErpIntegration
4
4
  module Fulfil
5
5
  class Client
6
+ FORMATTER = ErpIntegration::Middleware::Formatter
7
+
6
8
  attr_reader :api_keys_pool, :base_url
7
9
  attr_writer :connection, :faraday_adapter, :rotate_statuses
8
10
 
@@ -35,7 +37,7 @@ module ErpIntegration
35
37
  # Custom middleware for rotating API keys
36
38
  faraday.use ErpIntegration::Middleware::ApiKeysRotation, rotation_options
37
39
  # Custom middleware for logging requests and responses
38
- faraday.use ErpIntegration::Middleware::Logger, @logger if @logger
40
+ faraday.use ErpIntegration::Middleware::Logger, @logger, formatter: FORMATTER if @logger
39
41
 
40
42
  # Adapter definition should be last in order to make the json parsers be loaded correctly
41
43
  faraday.adapter faraday_adapter
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ErpIntegration
4
+ # The Logger class is a simple wrapper around the logger object.
5
+ class Logger
6
+ delegate :debug, :info, :warn, :error, :fatal, to: :logger, allow_nil: true
7
+
8
+ def initialize(logger = nil)
9
+ @logger = logger
10
+ end
11
+
12
+ # Logs the given tags if the logger is present.
13
+ # If the logger does not respond to `tagged`, it logs the tags as an info message.
14
+ def with_tags(*tags)
15
+ return yield unless logger
16
+
17
+ if logger.respond_to?(:tagged)
18
+ logger.tagged(*tags) { yield }
19
+ else
20
+ logger.info("Requested ERP with #{tags.join(', ')}")
21
+ yield
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :logger
28
+ end
29
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ErpIntegration
4
+ module Middleware
5
+ # The {Formatter} class is a custom formatter for the Faraday logger.
6
+ # It logs the rate limiter headers in the response.
7
+ class Formatter < Faraday::Logging::Formatter
8
+ def response(env)
9
+ super
10
+ public_send(log_level, 'response', &rate_limiter_headers(env.response_headers))
11
+ end
12
+
13
+ # Formats the rate limiter headers.
14
+ # @param headers [Hash]
15
+ def rate_limiter_headers(headers)
16
+ proc do
17
+ [
18
+ limit(headers),
19
+ remaining(headers),
20
+ reset_at(headers)
21
+ ].join(', ')
22
+ end
23
+ end
24
+
25
+ def limit(headers)
26
+ "Rate Limit #{headers['x-ratelimit-limit']}"
27
+ end
28
+
29
+ def remaining(headers)
30
+ "Remaining Limit #{headers['x-ratelimit-remaining']}"
31
+ end
32
+
33
+ def reset_at(headers)
34
+ "Rate Limit Reset at #{Time.at(headers['x-ratelimit-reset'].to_i).utc}"
35
+ end
36
+ end
37
+ end
38
+ end
@@ -20,15 +20,9 @@ module ErpIntegration
20
20
 
21
21
  def call(env)
22
22
  api_key_fragment = sanitize_api_key(env.request_headers['X-API-KEY']) || 'none'
23
+ request_uuid = SecureRandom.uuid
23
24
 
24
- if @logger.respond_to?(:tagged)
25
- @logger.tagged("API key *#{api_key_fragment}") do
26
- @formatter.request(env)
27
-
28
- @app.call(env).on_complete { |response| on_complete(response) }
29
- end
30
- else
31
- @logger.info("Requested ERP with API key *#{api_key_fragment}")
25
+ @logger.with_tags(api_key_tag(api_key_fragment), request_uuid) do
32
26
  @formatter.request(env)
33
27
 
34
28
  @app.call(env).on_complete { |response| on_complete(response) }
@@ -48,6 +42,10 @@ module ErpIntegration
48
42
  def sanitize_api_key(api_key)
49
43
  api_key[-4..-1] if api_key
50
44
  end
45
+
46
+ def api_key_tag(api_key_fragment)
47
+ "API key *#{api_key_fragment}"
48
+ end
51
49
  end
52
50
  end
53
51
  end
@@ -7,7 +7,7 @@ module ErpIntegration
7
7
  # the rate limiter by the API key.
8
8
  #
9
9
  # The `within_limit` method should yield to the block if the rate limit is not exceeded.
10
- REQUIRED_METHODS = %i[api_key_fragment within_limit].freeze
10
+ REQUIRED_METHODS = %i[api_key_fragment name within_limit].freeze
11
11
 
12
12
  class << self
13
13
  # Validates that the rate limiter object responds to the required methods.
@@ -29,7 +29,7 @@ module ErpIntegration
29
29
  # @param api_key [String]
30
30
  # @return [Object] The rate limiter object.
31
31
  def find_by_api_key(api_key)
32
- rate_limiters[api_key] || unlimited
32
+ new(rate_limiters[api_key] || unlimited)
33
33
  end
34
34
 
35
35
  # Returns an unlimited rate limiter.
@@ -53,11 +53,30 @@ module ErpIntegration
53
53
  end
54
54
  end
55
55
 
56
+ delegate :name, to: :@rate_limiter
57
+
58
+ def initialize(rate_limiter)
59
+ @rate_limiter = rate_limiter
60
+ end
61
+
62
+ def within_limit(&block)
63
+ ErpIntegration.config.logger.with_tags(@rate_limiter.name) do
64
+ @rate_limiter.within_limit(&block)
65
+ end
66
+ end
67
+
56
68
  # {Unlimited} is a rate limiter that allows all requests.
57
69
  # When the rate limiter wasn't found by the API key, it defaults to this class.
58
70
  # Or if the `rate_limiters` option is not set in the configuration.
59
71
  class Unlimited
60
72
  # Executes the block without any restrictions.
73
+
74
+ attr_reader :name
75
+
76
+ def initialize
77
+ @name = 'unlimited'
78
+ end
79
+
61
80
  def within_limit
62
81
  yield
63
82
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ErpIntegration
4
- VERSION = '0.56.0'
4
+ VERSION = '0.58.0'
5
5
  end
@@ -12,12 +12,14 @@ require_relative 'erp_integration/version'
12
12
  require_relative 'erp_integration/errors'
13
13
  require_relative 'erp_integration/api_keys_pool'
14
14
  require_relative 'erp_integration/rate_limiter'
15
+ require_relative 'erp_integration/logger'
15
16
  require_relative 'erp_integration/configuration'
16
17
 
17
18
  # Middleware
18
19
  require_relative 'erp_integration/middleware/api_keys_rotation'
19
20
  require_relative 'erp_integration/middleware/error_handling'
20
21
  require_relative 'erp_integration/middleware/logger'
22
+ require_relative 'erp_integration/middleware/formatter'
21
23
 
22
24
  # HTTP clients
23
25
  require_relative 'erp_integration/fulfil/client'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: erp_integration
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.56.0
4
+ version: 0.58.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefan Vermaas
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-11-15 00:00:00.000000000 Z
11
+ date: 2024-12-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -317,8 +317,10 @@ files:
317
317
  - lib/erp_integration/gift_card.rb
318
318
  - lib/erp_integration/internal_shipment.rb
319
319
  - lib/erp_integration/location.rb
320
+ - lib/erp_integration/logger.rb
320
321
  - lib/erp_integration/middleware/api_keys_rotation.rb
321
322
  - lib/erp_integration/middleware/error_handling.rb
323
+ - lib/erp_integration/middleware/formatter.rb
322
324
  - lib/erp_integration/middleware/logger.rb
323
325
  - lib/erp_integration/party_address.rb
324
326
  - lib/erp_integration/product.rb
@@ -369,7 +371,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
369
371
  - !ruby/object:Gem::Version
370
372
  version: '0'
371
373
  requirements: []
372
- rubygems_version: 3.5.6
374
+ rubygems_version: 3.2.22
373
375
  signing_key:
374
376
  specification_version: 4
375
377
  summary: Connects Mejuri with third-party ERP vendors