ostinelli / net-http2

NetHttp2 is an HTTP/2 client for Ruby.
MIT License
140 stars 31 forks source link

[Question] Timeouts for async calls #19

Closed nattfodd closed 3 years ago

nattfodd commented 7 years ago

I have a code that sends multiple async requests to the server. After all async calls are made, I call @client.join to wait until streams are closed. But sometimes they aren't for a huge amount of time (2-3 hours).

I read, that I need to implement my own timeout logic for such case. Okay. If I just wrap .join with a timeout, it's okay:

begin
  Timeout.timeout(60) { @client.join }
rescue Timeout::Error
  # Some code executed after failure
end

But, in a current implementation, we just stop waiting for streams and go next. But what I need is to detect which async calls were successful, and which ones were not, and then retry failed deliveries later.

Is there any recommended way to deal with it, or should I go back to a slower sync requests? And is there any way to close some streams that timeouted?

ostinelli commented 7 years ago

I would avoid using the Timeout module as much as possible (reference).

To solve this, an addition to the library is probably needed. I'd suspect the best place to implement a timeout would be to try and trigger the :on_close event here. Then it would just be a matter of propagating the option from the async call to there.

I'd need more time to investigate though.

jhottenstein commented 5 years ago

We are currently running into a problem with this as well.

Would an elapsed time check inside client#join be ok with you? Something like:

    def join
      starting_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
      while !@streams.empty? && Process.clock_gettime(Process::CLOCK_MONOTONIC) - starting_time < @join_timeout do
        sleep 0.05
      end
    end

The other idea that i tried was to add a timeout to the IO.select calls in the socket loop. The downside to this approach is that it becomes an idle timeout instead of a timeout around the join call.