njh / ruby-mqtt

Pure Ruby gem that implements the MQTT protocol, a lightweight protocol for publish/subscribe messaging.
http://www.rubydoc.info/gems/mqtt
MIT License
538 stars 135 forks source link

Major issue while using Thread to catch exception #160

Open Toucouleur66 opened 9 months ago

Toucouleur66 commented 9 months ago

Hello

Using Rails 6.1.7.6 and Ruby 2.6.6 having a big issue while trying to catch server when disconnected.

Please consider this working code:

Thread.handle_interrupt(Exception => :on_blocking) do
        begin
          loop do
            break unless @running

            if ensure_client_connected
              next
            end

            @client.get do |topic, message|
              Rails.logger.info("🔺 #{topic}: #{message}")
            end
          end
         # rescue MQTT::ProtocolException => e
        rescue Exception => e
          Rails.logger.error("🏓 MQTT disconnected: #{e.message}")
          # Try to reconnect
          ensure_client_connected
        end
      end

So let's says my connection is up, if server is down, it's going to trigger MQTT::ProtocolException (from ib/mqtt/packet.rb:223:in read_byte: Failed to read byte from socket (MQTT::ProtocolException))

As you already knows, the code above is not creating a new Thread, and because I need to subscribe to topics with a dedicated Thread on a Sidekick server, let's replace

Thread.handle_interrupt(Exception => :on_blocking) do with Thread.new do

Now my app is crashing for good whenever MQTT client is disconnected although I handle an exception to trigger it:

Traceback (most recent call last):
        3: from /Users/gems/ruby-2.6.6/bundler/gems/ruby-mqtt-271ee631f128/lib/mqtt/client.rb:278:in `block in connect'
        2: from /Users/gems/ruby-2.6.6/bundler/gems/ruby-mqtt-271ee631f128/lib/mqtt/client.rb:471:in `receive_packet'
        1: from /Users/gems/ruby-2.6.6/bundler/gems/ruby-mqtt-271ee631f128/lib/mqtt/packet.rb:30:in `read'
/Users//gems/ruby-2.6.6/bundler/gems/ruby-mqtt-271ee631f128/lib/mqtt/packet.rb:223:in `read_byte': Failed to read byte from socket (MQTT::ProtocolException) 

I studied a lot your documentation, but didn't find a way to handle this properly.

I tried to apply this method: https://github.com/njh/ruby-mqtt/issues/142#issuecomment-1303535723

adding this to my code:

  MQTT::Packet.prepend(Module.new do
    def read_byte
      super
    rescue ::Exception => ex
      Thread.current[:parent].raise(ex)
    end
  end)

But it didn't help unfortunately

Thanks by advance for any help