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

Add timeout option #72

Merged
merged 1 commit into from
Jan 7, 2020
Merged

Add timeout option #72

merged 1 commit into from
Jan 7, 2020

Conversation

neroleung
Copy link
Contributor

I wanted to set a longer timeout for background jobs but a shorter timeout for synchronize requests. This allows users to specify a timeout if they so desire.

@dblock
Copy link
Collaborator

dblock commented Jan 3, 2020

The current mechanism to do this would be

Graphlient::Client.new('http://test-graphql.biz/graphql') do |client|
      client.http do |h|
        h.connection do |c|
          c.timeout = 20
        end
      end
    end

I can see how specifying the timeout in the client constructor is easier. But I worry that we're forcing all adapters into supporting timeout, so the next person will want read_timeout vs. write_timeout and then we open a can of worms for all the options.

What do you think about generalizing access to adapter options instead?

client = Graphlient::Client.new('https://test-graphql.biz/graphql',
  headers: {
    'Authorization' => 'Bearer 123'
  },
  http_options: {
    timeout: 20
  }
)
client = Graphlient::Client.new('https://test-graphql.biz/graphql',
  headers: {
    'Authorization' => 'Bearer 123'
  },
  http_options: {
    read_timeout: 20,
    write_timeout: 30
  }
)

@yuki24
Copy link
Collaborator

yuki24 commented Jan 3, 2020

I'm in favor of @dblock's second suggestion.

@neroleung
Copy link
Contributor Author

Thanks for the suggestions. I've change the code to do http_options - read_timeout and write_timeout.

@dblock
Copy link
Collaborator

dblock commented Jan 4, 2020

I believe this doesn't work when timeouts are set to 0 or nil, which are both valid values for options. Check everywhere for key presence in the options.

Now, this is better from the interface POV but we can be future-proof and client-agnostic with a bit of meta programming.

Instead of

          Net::HTTP.new(uri.host, uri.port).tap do |client|
            client.use_ssl = uri.scheme == 'https'
            client.read_timeout = http_options[:read_timeout] if http_options[:read_timeout]

            if client.respond_to?(:write_timeout=)
              client.write_timeout = http_options[:write_timeout] if http_options[:write_timeout]
            end

Do

          Net::HTTP.new(uri.host, uri.port).tap do |client|
            client.use_ssl = uri.scheme == 'https'
            http_options.each_pair do |k, v|
               client.send("#{k}=", v)
            end

Check in tests that we get a proper/useful error when trying to assign write_timeout to a client that doesn't support it, too. Might need some better rescue in the actual implementation.

@neroleung
Copy link
Contributor Author

@dblock, for the meta-programming part, did you mean to do it in just http_adapter.rb, or both http_adapter.rb and faraday_adapter.rb?

@dblock
Copy link
Collaborator

dblock commented Jan 6, 2020

@dblock, for the meta-programming part, did you mean to do it in just http_adapter.rb, or both http_adapter.rb and faraday_adapter.rb?

Both. I think Graphlient should serve as a passthrough to whatever options users specify, and not try to be smart about timeout options.

@neroleung
Copy link
Contributor Author

Updated the code with a shared private method #configure_http_options. Please let me know what you think. Thx~

http_options.each do |k, v|
set_method_name = "#{k}="

client_options.send(set_method_name, v) if client_options.respond_to?(set_method_name)
Copy link
Collaborator

@dblock dblock Jan 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be failing loudly, we want callers to know that they are trying to set an option that is not supported. Specialize an exception, rescue NameError here and raise that exception. Make sure to add a test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rescuing NoMethodError and re-raise a new Graphlient::Errors::HttpOptionsError now. Thx for all the feedback!

@dblock
Copy link
Collaborator

dblock commented Jan 6, 2020

Updated the code with a shared private method #configure_http_options. Please let me know what you think. Thx~

Almost there. Let's fail loudly on invalid options and we're good to go.

@dblock
Copy link
Collaborator

dblock commented Jan 7, 2020

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants