Particle.publish() took very long time up to ~12+ s to return

I have a code snippet like this put in the loop().

auto startTime = millis();
if(Particle.connected()) {
auto duration = (millis() - startTime);

Normally duration would be in range ~ 1000 ms - 2000 ms. But occasionally it can reach 12000+ ms!!!

from the serial log, there seems to be no system event happening, no disconnection, just a normal one. And my publication rate is just 1 event/15 s.

Anyone can explain how publish can take this much time? And worse this is a blocking call.

I would try a delay after Particle.publish() - comment / uncomment to try the two different delays out below:

if(Particle.connected()) {
  //delay(1000);     // this will block for 1000ms allowing only ONE Particle.process()
  // or
  for(uint32_t _ms = millis(); millis() - _ms < 1000; Particle.process());  // many calls of Particle.process()

The rest of your code in loop() should be non-blocking. If you are using SYSTEM_MODE(MANUAL) you will need to place Particle.process() in your loop().

Also, there is a library you might check out where you can publish asynchronously (Great Stuff !!):

A 12 second delay is about what would be expected if the first publish packet was lost (no acknowledgement receive), or the ACK was lost. There’s a delay before retry, and three retries.

thank you @robc, may I know the point of the delay or call Particle.process() many times and how it may help? thanks for the library, I’d definitely checks it out!

Thank you @rickkas7, so just to cofirm:

12 s = to publish (NO ACK) + delay + 3 times retry?

Also, since the API returns true, can I say finally the data was successfully published despite the long duration it took?

If possible, please post your actual code. That will help in the discussion.

There is a rate limit on the number of calls of Particle.publish() statements. So, typically, while initially developing your code, make a 1 second delay after each statement to help you stay within the rate limit just in case your code calls many publish statements in a row. Here is more about this:

A delay(x000); statement can be considered blocking.

Your loop() routine iterates endlessly and every time it “loops” it calls Particle.process() once, UNLESS your using SYSTEM_MODE(MANUAL). In the commented out statement of the example I offered, using the For() statement which calls Particle.process() can be considered a non-blocking delay.

Here is a thread which might help:

1 Like

Here is some more information:

Thank you @robc, I appreciate it.

Anyway, based on this, not all use cases we need to add 1s delay in between publish. If the interval in between publish is long, we can skip that delay.

Is it possible to make it fail instead of retrying and blocking for that long ?

Yes. You can try using “NO_ACK” in your Particle.publish() statement. Sorry for the double post of the link, but, it is a helpful writeup by @rickkas7 about this parameter and others:

also, here is a link to the docs with more information about “NO_ACK”:

Instead of Particle.publish() I utilize publishQueue.publish() whenever possible. You will need to install the library, PublishQueueAsyncRK, to use it but the results are non-blocking. For example:

publishQueue.publish("xyz sensor", "does NOT exist", PRIVATE, WITH_ACK);

will not block while the “WITH_ACK” is dealt with. There is a link near the top of this thread for more info about the library.