Mosquitto-PHP icon indicating copy to clipboard operation
Mosquitto-PHP copied to clipboard

Missing messages when not using loopForever()

Open rosshettel opened this issue 7 years ago • 5 comments

Been using this library to listen for MQTT messages in a constant running daemon process. However, I can't use loopForever() as the daemon needs to call other methods during each cycle. I call loop() about 20 times every 5 seconds. However, during the time loop() is not being called, we miss MQTT messages coming into the client.

Our client is setup with QoS 2 and a persistent session. If I use loopForever() I can see that I don't miss any messages. Is there something I'm missing with the loop() method? I'm not sure why it's missing messages.

rosshettel avatar Jan 25 '18 16:01 rosshettel

I can confirm this is happening. Even when calling loop() every few usecs with 0 or 1 timeout I will miss messages when under heavy load (> 3k or 4k publishes per sec). When calling loopForever() all messages are published and consumed properly.

davidg246819 avatar Apr 06 '18 15:04 davidg246819

I'll see if I can replicate this behaviour. I've not had a lot of time to work on this recently, though hopefully I can fix that soon.

mgdm avatar Apr 06 '18 19:04 mgdm

Hi @mgdm,

Thanks for the extension.

I have also noticed this behaviour if we publish messages back to back in about 100 in 1 sec. To reproduce, have a topic published in the loop of around 300 iterations.

So I switched to loopForever, but for some reason, it never exits if I give it a timeout value.

A code snippet is here: try { $cfg = $this->config->item('mqtt'); $mid = 0; $client = new Mosquitto\Client("web_api_client"); $client->setCredentials($cfg['user'], $cfg['password']); $client->onConnect(function() use ($client, &$mid, $toTopic, $toPayload) { $mid = $client->publish($toTopic, $toPayload, 1); } ); $client->onPublish(function() use ($client,$fromTopic) { $client->subscribe($fromTopic, 1); }); $client->onMessage( function($response) use ($client, &$responseTopic, &$responseMessage, &$responseReturn) { $responseTopic = $response->topic; $responseMessage = $response->payload; $client->exitLoop(); $client->disconnect(); }); $client->connect($cfg['host'], 1883, 5); $client->loopForever(100); $responseReturn = array('topic'=> $responseTopic, 'message' => $responseMessage); } catch (Exception $e) { $response = 'Exception: ' .$e->getMessage(); $responseReturn = false; }

Please let me know if I am doing something wrong.

Thanks for the help in advance.

hstanda avatar Jul 04 '19 05:07 hstanda

Hi, Apologies for the late response, I've been on holiday. The timeout you give in loopForever() means each trip around the loop is going to take up to that period of time, I wonder if that could explain it being slow. I'll see if I can reproduce this myself and try and instrument it. The messages that come in should be being buffered, but it may take several loop() calls to process one message depending on the QoS value that was set and a few other variables. Do you see some messages coming in, then some missing, and later ones coming in?

mgdm avatar Jul 14 '19 21:07 mgdm

@mgdm Thanks for replying I need to set a timeout for loopForever().

Goal: disconnect from the Broker if the given time is passed or the subscribed topic received.

I have snippet above, it will be very helpful if you can guide me to achieve the goal.

hstanda avatar Jul 16 '19 00:07 hstanda