ostinelli / apnotic

A Ruby APNs HTTP/2 gem able to provide instant feedback.
MIT License
477 stars 95 forks source link

Callback for :response not firing in async #116

Open joshleaves opened 2 years ago

joshleaves commented 2 years ago

Hi,

I've noticed that following the async code example from the documentation leads to some pushes not being sent, in spite of using connection.join to wait for all pushes to be sent and for all responses to be received.

Here is my (pseudo) code, it's a job within a single-threaded Sidekiq:

class ApnsJob < ApplicationJob
  def connection
    @@connection ||= Apnotic::Connection.new
  end

  def perform()
    @cb_response = 0
    @cb_close    = 0

    sessions.map{|s| [s, build_notification(s)] }.each do |session, notification|
      push = connection.prepare_push(notification)
      push.http2_request.on(:close) do
        @cb_close += 1
      end

      push.on(:response) do |response|
        @cb_response += 1
        next if response.ok?

        dispatch_error(response, session)
      end

      connection.push_async(push)
    end

    connection.join

    raise "Invalid :close callbacks" unless @cb_close == sessions.length
    raise "Invalid :response callbacks" unless @cb_response == sessions.length
  end

end

Around 99% of jobs go through perfectly, but once in a while, one will raise because the :response callback was never fired, and my devices don't receive APNS either. I added a check on the HTTP2 Request's :close callback too and the callback is never fired too.

By this point, I've digged in both this library and net-http2, and even checked if rpush was doing anything different, but to no avail.

My best theory (which I don't even believe in) is to suspect this may be due to connection.join() being ran before connection.push_async() has had time to add the HTTP stream, but given what I understood from the code, this seems highly impossible.

Another could be the single-connection reuse, but I don't see how since I am running Sidekiq workers single-threaded.

Can you see something I may be missing or doing completely wrong, or if that is indeed an issue with the library?

Thank you for your support