lostisland/faraday-net_http

Implement `Connection#close`

AlexWayfer opened this issue · 5 comments

Can we do it for Net::HTTP?

I found #finish method, but not sure it's suitable.

I'm no expert but I don't think that's necessary because we use #start and that should automatically "finish" the connection at the end of the request according to the documentation.

Net::HTTP.start(hostname) do |http|
  # Session started automatically before block execution.
  http.get(path_or_uri, headers = {})
  http.head(path_or_uri, headers = {})
  http.post(path_or_uri, data, headers = {})  # Can also have a block.
  http.put(path_or_uri, data, headers = {})
  http.delete(path_or_uri, headers = {Depth: 'Infinity'})
  http.options(path_or_uri, headers = {})
  http.trace(path_or_uri, headers = {})
  http.patch(path_or_uri, data, headers = {}) # Can also have a block.
  # Session finished automatically at block exit.
end

Hm…

Isn't Faraday::Connection#close the way to abort current request?

I'm looking for a way to do this (I have pretty long polling requests, maybe for 1 minute each).

And will not calling Net::HTTP#finish will do this?

I'm not an expert too. 😅

Oh I see, you're talking about separate threads accessing the same connection?
#close is more intended to close a persistent connection, rather than abort an existing request, but I can see why you'd want to abort a long-running request (and assuming the use of timeouts is not an option).

And will not calling Net::HTTP#finish will do this?

To be honest I don't know the answer to this 😅, but if you could double-check this locally with "plain Net::HTTP" and it works as expected, we could add this in. It's not gonna be easy since the adapter has not been built with parallelism in mind, but I think we can find some creative solutions to get it done 😄 (top-of-mind idea: keep a list of "pending" requests in the adapter and "finish" them all when #close is called)

Or we could always introduce a new #abort method if that makes more sense 🤔
Let's chat once we know if it works 👍

I can see why you'd want to abort a long-running request (and assuming the use of timeouts is not an option).

Yeah: it's polling requests, designed to be long, one-by-one, like an alternative to web-sockets or something. There is nothing about timeouts for me.

It's not gonna be easy since the adapter has not been built with parallelism in mind,

It's not a lot of parallelism for me, my case. I just have simple Signal.trap('INT') for now, and I'd like to gracefully stop these long polling requests instead of waiting for dozens of seconds, you know.

To be honest I don't know the answer to this , but if you could double-check this locally with "plain Net::HTTP" and it works as expected, we could add this in.

I'm a bit lazy for this, and my case is not kind of urgent. But maybe my curiosity will take over. I've also created a few similar issues in other adapters, maybe now they seem stupid for me, but… let's wait for answers, and maybe new details and experiments will lead us to somewhere.

I wanted to create a discussion in Faraday repo firstly, but then I've found Connection#close method in documentation and its short description convinced me that this is the thing (what I need). And just a few adapters has implementation for this method.

Net::HTTP#finish just waiting for current request.

Simple testing code:

# frozen_string_literal: true

require 'dotenv/load'

require 'logger'

logger = Logger.new($stdout)

require 'net/https'

connection = Net::HTTP.new('api.telegram.org', 443)

connection.use_ssl = true

Signal.trap('INT') do
  ## Can't use `logger` here:
  ## > log writing failed. can't be called from trap context
  puts 'INT has been trapped...'
  connection.finish
end

logger.info 'Make request...'

response = connection.get "/bot#{ENV['BOT_API_TOKEN']}/getUpdates?offset=0&timeout=20"

logger.info 'Done.'

p response, response.body

I haven't found any method for aborting request.

I also tried to change timeouts and retries to 0 values "on the fly" — nothing.

You can change max_retries = -1 and get an exception… but it's like regular raise and non graceful at all.

You can close this issue if you want to. I don't know what to do and how I can reach desirable even with 3rd-party adapters. Do they have such functionality or no, and how it should be triggered from a Faraday instance.