Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ShopifyAPI::Errors::HttpResponseError is missing response object with header "retry-after" #1038

Closed
kaarelss opened this issue Oct 13, 2022 · 0 comments · Fixed by #1040
Closed

Comments

@kaarelss
Copy link
Contributor

kaarelss commented Oct 13, 2022

Issue summary

ShopifyAPI::Errors::HttpResponseError is missing response object. It was included in the error in previous versions of the gem.

Expected behavior

ShopifyAPI::Clients::HttpClient request method passes only HTTP code when initializing ShopifyAPI::Errors::HttpResponseError.

unless [429, 500].include?(response.code)
raise ShopifyAPI::Errors::HttpResponseError.new(code: response.code.to_i), error_message
end
if tries == request.tries
raise ShopifyAPI::Errors::HttpResponseError.new(code: response.code), error_message if request.tries == 1
raise ShopifyAPI::Errors::MaxHttpRetriesExceededError.new(code: response.code),
"Exceeded maximum retry count of #{request.tries}. Last message: #{error_message}"
end

ShopifyAPI::Errors::HttpResponseError should contain addition attribute response, and should be passed when initializing error in the lines above.

Actual behavior

In previous versions (pre v10) of the ShopifyAPI gem there was response object stored within the error object. So in case of HTTP 429 Too Many Requests, "retry-after" header was available within the error and it was possible to make custom retry logic when call limit is reached. Now response object is missing, so there is no way to get "retry-after" value.

Steps to reproduce the problem

  1. Install gems
gem install "concurrent-ruby"
gem install "shopify_api"
  1. Change api_key, api_secret_key, shop and access_token in the snippet
  2. Execute snippet
require "shopify_api"
require "concurrent-ruby"

ShopifyAPI::Context.setup(
  api_key: "******* Your API key ********",
  api_secret_key: "******* Your API secret ********",
  api_version: "2022-04",
  host_name: "",
  scope: "write_products",
  is_private: false,
  is_embedded: true,
  session_storage: ShopifyAPI::Auth::FileSessionStorage.new,
)

thread_pool = Concurrent::FixedThreadPool.new(100)

error = nil
100.times.each do |i|
  thread_pool.post do
    session = ShopifyAPI::Auth::Session.new(
      shop: "******* Your shop ********",
      access_token: "******* Your token ******"
    )
    ShopifyAPI::Context.activate_session(session)

    product = ShopifyAPI::Product.new(session: ShopifyAPI::Context.active_session)
    product.title = "Product #{i}"
    product.handle = "product-#{i}"
    product.save!
  rescue ShopifyAPI::Errors::HttpResponseError => e
    if e.code == 429
      # We would like to make our own retry logic here when call limit is reached.
      # One way would be to store response object within error, so we can get 'retry-after' header
      begin
        retry_after = e.response.headers["retry-after"]
      rescue StandardError => e
        error = e
      end
    end
  end
end

thread_pool.shutdown
thread_pool.wait_for_termination
raise(error) if error.present?

This snippet will produce:
undefined method 'response' for #<ShopifyAPI::Errors::HttpResponseError:0x0000000147124470> (NoMethodError)
as it indicates where response object would be used.

Specifications

  • shopify_api version: 12.0.0
  • Shopify API version used (example: 2020-04):
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant