PublishQuequeAsyncRK - escaping the long winded loop

@rickkas7, am implementing your excellent PublishQuequeAsyncRK library, https://github.com/rickkas7/PublishQueueAsyncRK, v0.0.4.

Have added a simple enhancement to invoke a callback within the checkQuequeState() method when there has been excessive time elapsed in waiting for transmission and/or acknowledgement, which may never happen.

The idea is that the callback function handles the “stuck” event, for example by saving the event to file on an SD CARD so as to be processed in an offline manner later on. The callback returns a boolean to indicate “you can delete the event”.

Am wondering if you could comment on this piece of your code ("// UMD comments" are mine):

                auto request = Particle.publish(eventName, eventData, data->ttl, flags);

		// Use this technique of looping because the future will not be handled properly
		// when waiting in a worker thread like this.
		while(!request.isDone()) {   // UMD - when will isDone() return true?
			delay(1);
		}
		bool bResult = request.isSucceeded();   // UMD - what is the difference between 
                                                                                // isSuceeded() and isDone?
		if (bResult) {
			// Successfully published
			log.info("published successfully");
			discardOldEvent(false);
		}
		else {
			// Did not successfully transmit, try again after retry time
			log.info("published failed, will retry in %lu ms", failureRetryMs);
			stateHandler = &PublishQueueAsync::waitRetryState;
		}

Am just wondering if request.isDone() means “transmitted” and request.isSucceeded() means “ACK received”.
.
I have been able to produce a situation where request.isDone() does not return true by turning of data on a mobile hotspot (hence the callback strategy enhancement), and hence never exiting the loop.

Next question - wondering why discardOldEvent() has the option to remove the first or second event?

A callback would probably be reasonable to add.

isDone() checks to see if the future resolved.

isSucceeded() is basically the result from Particle.publish. But isSucceeded() won’t be valid until isDone() is true.

The discardOldEvent function deletes the oldest (first) event in the queue if not currently publishing.

However, if a publish is currently in progress, we don’t want to delete the item that’s currently being sent, so we delete the second event.

1 Like

@rickkas7, got it re isDone() and isSucceeded() - makes sense.

Do you find it surprising that I have been able to get a situation where isDone() does not return true?

I would have thought that a timeout should have been kicked off by Particle.publish()…

@rickkas7,

I said:

I would have thought that a timeout should have been kicked off by Particle.publish()…

I now say:

Happy to confirm that Particle.publish() does return when there is no connection to the cloud after about 7 seconds

I had missed the " && Particle.connected() " in the if statement at the top of checkQueueState(), which meant that Particle.publish() was not being called which led me down the wrong path.

Am now going to modify my callback strategy to take this into account.

Case closed!