HubSpot / hubspot-api-ruby

HubSpot API Ruby Client Libraries for V3 version of the API
Apache License 2.0
114 stars 58 forks source link

No more global retry settings? #247

Open jacobjlevine opened 1 year ago

jacobjlevine commented 1 year ago

Hey folks! I'm currently using 14.3.0, but looking into upgrading to more recent versions of this gem. In the version we're currently using, it's possible to set a global option for error retry using the error_handler method of the configuration object. It looks like newer versions of the gem allow you to set retry options at the individual API request level, but is it possible to still set global settings? It feels like having global settings that can be overwritten for individual requests is an obvious way to go here to minimize unnecessary/duplicate code in our applications (not to mention opportunities for human error).

timherby commented 1 year ago

Running into this too.

I would expect to be able to do this:

      options = {
        access_token: access_token,
        error_handler: {
          [429] => {
            max_retries: 5,
            seconds_delay: 2,
            retry_block: lambda do
              puts "Rate Limited, retried"
            end
          }
        }
      }

      @api_client ||= Hubspot::Client.new(options)

But I think I'm going to have to do something like this per object type I'm going to invoke:

@api_client.crm.objects.search_api.api_client.config.configure do |config|
  config.error_handler = {
                                 [429] => {
                                   max_retries: 5,
                                   seconds_delay: 2,
                                   retry_block: lambda do
                                     puts "Rate Limited, retried"
                                   end
                                 }
                               }
end

@api_client.crm.objects.search_api.do_search(object_type: OBJECT_TYPE, body: {...})

Though that's still not working...

It appears that the library regenerates a new api_client every time you call:

> api_client.crm.objects.search_api.api_client
=> #<Hubspot::Crm::Objects::ApiClient:0x0000000112dbca50 
> api_client.crm.objects.search_api.api_client
=> #<Hubspot::Crm::Objects::ApiClient:0x0000000111646768

So you can't store any configuration there.

Which is caused by this logic in hubspot/discovery/base_module_client.rb:

Screenshot 2023-08-20 at 11 20 39 AM

which will re-create every object along the path every time it is invoked.

I also cannot access the default configuration to change it like this:

 Hubspot::Crm::Objects::Notes::Configuration.default

And the default initializer for the default configuration doesn't take in any parameters, so it has the base parameters each time:

          def self.default
            @@default ||= Configuration.new
          end

As a workaround, I'm having to cache and manually configure each API I'm going to use:

def search_api
  return @search_api if @search_api

  @search_api = @api_client.crm.objects.search_api
  apply_retries(@search_api)
  @search_api
end

def apply_retries(api)
  api.config.error_handler = {
    [429] => {
      max_retries: 5,
      seconds_delay: 2,
      retry_block: lambda do
        puts ("Rate Limited, retried")
      end
    }
  }
end

Which seems to be stable, but is a bit of a ridiculous workaround.

If there's an easier way to configure this gem, please let me know @atanasiuk-hubspot and @jausura as I cannot find any other documentation about it besides this thread.

Sokre95 commented 1 year ago

timherby This reminded me a lot of the time I was trying to figure out how to configure retries and actually ran into the same problem as you, so thank you for sharing your detailed explanation. At the end I'm passing an retry config hash in every api call 🤷‍♂️. But that approach opens up another problem 😅

oboxodo commented 1 month ago

This seems related: https://github.com/HubSpot/hubspot-api-ruby/pull/161#pullrequestreview-2328734003