Open collimarco opened 2 years ago
Another related question...
If I use the sync push, and I add the "on error" callback:
connection = Apnotic::Connection.new(cert_path: StringIO.new(apns_cert))
connection.on(:error) { |exception| puts "Exception has been raised: #{exception}" }
What happens to the main code when there is an exception in the background thread?
Does connection.push
raises an exception? Does it return nil? Or something else happens?
What happens to the main code when there is an exception in the background thread? Does connection.push raises an exception? Does it return nil?
Ok, it seems that the call connection.push
waits 30 seconds (timeout) and then returns nil
... This is an unexpected behavior.
If the APNs certificate is expired (or a similar error occurs), why wait 30 seconds in the connection.push
call?
We're seeing the same behavior, connection.push
keeps holding the connection for 60 seconds (NetHttp2::Client
's default) till it times out.
In our case we are using a connection pool, so the issue has an even wider scope:
connection_pool.with
grab all 5 connections. Immediately Connection reset by peer
is raised and caught in the on(:error)
definition, but the connections themselves are not checked in and are held for 60 secondsThus, any new invocation of the async job will raise ConnectionPool::Timeout: waited for 5 seconds
because all connections are in use.
Probably the connection should be checked in/shutdown after the error is returned? How can this be achieved?
@collimarco the nil
on timeout is indeed unexpected, but it's in the docs https://github.com/ostinelli/apnotic#blocking-calls
update: Apologies for hijacking, but my case seems relevant, even though we're running with connection pool. Also this seems related to connection timeouts
After some digging, it seems that the issue might be related to net-http2
's logic here
# /lib/net-http2/client.rb
def call(method, path, options={})
request = prepare_request(method, path, options)
ensure_open
new_stream.call_with request
end
Right now even if ensure_open
failed and ended up running the code inrescue EOFError
, emitting the on(:error)
for the Apnotic connection, the new_stream.call_with request
will still be called and will wait for the whole timeout duration 🤔
Hi @mcfoton,
If you want to make a pull request to address this it would be greatly appreciated.
Apnotic is mostly community supported at this point so that would be the main way for this to get fixed.
Thanks!
Thank you @benubois.
@benubois @ostinelli I'll see if I can do something about this, though the topic of threads is pretty new to me. Hopefully what I described above is at least the right direction 😌
And just for the record: another unhandled exception that we are seeing is Errno::ECONNRESET
thrown by ruby-2.7.3/lib/ruby/2.7.0/openssl/buffering.rb:322
and is also initially called by net-http2
's call
method with new_stream.call_with request
.
We are using this gem with sync pushes: https://github.com/ostinelli/apnotic#sync-pushes
This is the relevant code:
The problem is that
OpenSSL::SSL::SSLError
is not catched byrescue
, as you would expect.Basically the exception is raised, but
rescue
has not effect and therescue
code does not get executed.Is that because we don't set
connection.on(:error)
? Is there any way to raise all the exceptions normally so that therescue
in the above code can work? Or any workaround?Thanks