2
votes

I moved mqtt-hs to LTS-5.13 and compiled just fine with stack. Then I created the following subscriber to listen on a topic hierarchy. This is the subscriber code

{-# LANGUAGE OverloadedStrings #-}
module Main(main) where

import Control.Concurrent (threadWaitRead)
import System.Posix.Types
import Network.MQTT
import Network.MQTT.Logger

main :: IO ()
main = do
  conn <- connect defaultConfig { cLogger = warnings stdLogger, cHost = "192.168.0.1" }
  qos <- subscribe conn Confirm "/something" callback
  putStrLn "control-c to finish"
  threadWaitRead $ Fd 1

callback topic payload = putStrLn $ "A message was published to " ++ show topic ++ ": " ++ show payload

When I send something to the topic (using a simple Haskell publisher too), I am getting this in the console of this program:

control-c to finish
[Error] {handle: <socket: 3>}: recvLoop: end of file
[Error] recvLoop: No reconnect, terminating.

but no other output.

Both publisher and subscriber connect to a broker (Mosquitto). The subscriber seems to be Ok, the above happens only when receiving the message from the publisher. The above message also occurs when I stop the broker.

Any ideas?

Update

I cloned most recent mqtt-hs (0.3.0) and introduced this change

--- a/Network/MQTT.hs
+++ b/Network/MQTT.hs
@@ -448,9 +448,10 @@ recvLoop :: MQTT -> IO ()
 recvLoop m = loopWithReconnect m "recvLoop" $ \mqtt -> do
     h <- readMVar (handle mqtt)
     eof <- hIsEOF h
-    if eof
-      then ioError $ mkIOError eofErrorType "" (Just h) Nothing
-      else getMessage mqtt >>= dispatchMessage mqtt
+    getMessage mqtt >>= dispatchMessage mqtt
+    -- if eof
+    --   then ioError $ mkIOError eofErrorType "" (Just h) Nothing
+    --   else getMessage mqtt >>= dispatchMessage mqtt
   `catch`
     \e -> logWarning mqtt $ "recvLoop: Caught " ++ show (e :: MQTTException)

i.e, I disabled the EOF checking. Now the message is printed to the console, but the subscriber enters into a loop throwing [Warning] recvLoop: Caught EOF as fast as it can.

Is this a mosquito error or bug in mqtt-hs?

Update 2

I can confirm it works with ActiveMQ without the hack. Having said this, it is better if mqtt-hs could recover from broker closing connection to a subscriber.

1

1 Answers

1
votes

I believe that you might have it misconfigured. I'm currently using mqtt-hs in production and have almost no issues with it (barring a bug that has already been corrected in the project's github). The new update uses a TChan to have the messages delivered correctly as in a persistent connection, there is a chance the that some messages may be lost as the handler has not yet been made available.

You define the connection to the broker, but you don't tell the client about how the reconnections should be handled. For reference, I'm using something like the following at the moment:

mqttConfig :: HostName -> MQTTConfig
mqttConfig host = defaultConfig { cClean = False
                                , cClientID = "myClientId"
                                , cHost = host
                                , cUsername = Just "username"
                                , cPassword = Just "password"
                                , cKeepAlive = Just 10
                                , cReconnPeriod = Just 1
                                , cLogger = stdLogger }

Even though the version in use here is slightly updated, very little needed to change and reconnctions happen as needed when the broker (mosquitto as well here) goes down and then later recovers.