def listen_loop(routing_keys, &handler)
      @listen_timer = nil

      begin
        # Perform listen action based on current state
        case @listen_state
        when :choose
          # Choose listen method or continue as is if already listening
          # or want to delay choosing
          choose_listen_method
        when :check
          # Check whether really got connected, given the possibility of an
          # asynchronous WebSocket handshake failure that resulted in a close
          # Continue to use WebSockets if still connected or if connect failed
          # due to unresponsive server
          if @websocket.nil?
            if router_not_responding?
              update_listen_state(:connect, backoff_reconnect_interval)
            else
              backoff_connect_interval
              update_listen_state(:long_poll)
            end
          elsif (@listen_checks += 1) > CHECK_INTERVAL
            @reconnect_interval = RECONNECT_INTERVAL
            update_listen_state(:choose, @connect_interval = CONNECT_INTERVAL)
          end
        when :connect
          # Use of WebSockets is enabled and it is again time to try to connect
          @stats["reconnects"].update("websocket") if @attempted_connect_at
          try_connect(routing_keys, &handler)
        when :long_poll
          # Resorting to long-polling
          # Need to long-poll on separate thread if cannot use non-blocking HTTP i/o
          # Will still periodically retry WebSockets if not restricted to just long-polling
          if @options[:non_blocking]
            @event_uuids = process_long_poll(try_long_poll(routing_keys, @event_uuids, &handler))
          else
            update_listen_state(:wait, 1)
            try_deferred_long_poll(routing_keys, @event_uuids, &handler)
          end
        when :wait
          # Deferred long-polling is expected to break out of this state eventually
        when :cancel
          return false
        end
        @listen_failures = 0
      rescue Exception => e
        ErrorTracker.log(self, "Failed to listen", e)
        @listen_failures += 1
        if @listen_failures > MAX_LISTEN_FAILURES
          ErrorTracker.log(self, "Exceeded maximum repeated listen failures (#{MAX_LISTEN_FAILURES}), stopping listening")
          @listen_state = :cancel
          self.state = :failed
          return false
        end
        @listen_state = :choose
        @listen_interval = CHECK_INTERVAL
      end

      listen_loop_wait(Time.now, @listen_interval, routing_keys, &handler)
    end
def listen_loop(routing_keys, &handler)
      @listen_timer = nil

      begin
        # Perform listen action based on current state
        case @listen_state
        when :choose
          # Choose listen method or continue as is if already listening
          # or want to delay choosing
          choose_listen_method
        when :check
          # Check whether really got connected, given the possibility of an
          # asynchronous WebSocket handshake failure that resulted in a close
          # Continue to use WebSockets if still connected or if connect failed
          # due to unresponsive server
          if @websocket.nil?
            if router_not_responding?
              update_listen_state(:connect, backoff_reconnect_interval)
            else
              backoff_connect_interval
              update_listen_state(:long_poll)
            end
          elsif (@listen_checks += 1) > CHECK_INTERVAL
            @reconnect_interval = RECONNECT_INTERVAL
            update_listen_state(:choose, @connect_interval = CONNECT_INTERVAL)
          end
        when :connect
          # Use of WebSockets is enabled and it is again time to try to connect
          @stats["reconnects"].update("websocket") if @attempted_connect_at
          try_connect(routing_keys, &handler)
        when :long_poll
          # Resorting to long-polling
          # Need to long-poll on separate thread if cannot use non-blocking HTTP i/o
          # Will still periodically retry WebSockets if not restricted to just long-polling
          if @options[:non_blocking]
            @event_uuids = process_long_poll(try_long_poll(routing_keys, @event_uuids, &handler))
          else
            update_listen_state(:wait, 1)
            try_deferred_long_poll(routing_keys, @event_uuids, &handler)
          end
        when :wait
          # Deferred long-polling is expected to break out of this state eventually
        when :cancel
          return false
        end
        @listen_failures = 0
      rescue Exception => e
        ErrorTracker.log(self, "Failed to listen", e)
        @listen_failures += 1
        if @listen_failures > MAX_LISTEN_FAILURES
          ErrorTracker.log(self, "Exceeded maximum repeated listen failures (#{MAX_LISTEN_FAILURES}), stopping listening")
          @listen_state = :cancel
          self.state = :failed
          return false
        end
        @listen_state = :choose
        @listen_interval = CHECK_INTERVAL
      end

      listen_loop_wait(Time.now, @listen_interval, routing_keys, &handler)
    end
Perform listen action, then wait prescribed time for next action
 A periodic timer is not effective here because it does not wa

 @param [Array, NilClass] routing_keys for event sources of interest with nil meaning all

 @yield [event] required block called each time event received
 @yieldparam [Hash] event received

 @return [Boolean] false if failed or terminating, otherwise true