Is it a violation of the MQTT spec for a client to resend a QoS 1 message from a previous session when cleanSession=1? - session

The MQTT 3.1.1 spec, section 3.1.2.4 says
If CleanSession is set to 1, the Client and Server MUST discard any
previous Session and start a new one. This Session lasts as long as
the Network Connection. State data associated with this Session MUST
NOT be reused in any subsequent Session [MQTT-3.1.2-6].
The Session state in the Client consists of:
· QoS 1 and QoS 2 messages which have been sent to the Server,
but have not been completely acknowledged.
· QoS 2 messages which have been received from the Server, but
have not been completely acknowledged.
Meaning the client must discard unacked QoS 1 messages and not reuse any data from them in the new session.
However, there seem to be plenty of examples in the wild of clients resending unacked QoS 1 messages on a clean session reconnect.
Resending unacked messages is almost indistinguishable in this case from sending a new message with the same content, except for the DUP flag - is it wrong for a client to set the DUP flag when retrying unacked messages on a clean session?
Also, surely it's a violation to retry QoS 2 messages on a clean session reconnect, since that could potentially break the at most once delivery guarantee?

Related

The transaction was rolled back on failover however commit may have been successful

I have an application using jms that sends data to an ActiveMQ Artemis queue. I got an exception with this message:
The transaction was rolled back on failover however commit may have been successful
This exception is basically telling me that the message may or may not have reached the queue so I don't know if I need to send the message again. Whats the best way to handle an exception like this when:
I cannot send duplicate messages to applications on the other end of the queue.
and
I cannot skip a message.
I can't state it better than the ActiveMQ Artemis documentation:
When sending messages from a client to a server, or indeed from a server to another server, if the target server or connection fails sometime after sending the message, but before the sender receives a response that the send (or commit) was processed successfully then the sender cannot know for sure if the message was sent successfully to the address.
If the target server or connection failed after the send was received and processed but before the response was sent back then the message will have been sent to the address successfully, but if the target server or connection failed before the send was received and finished processing then it will not have been sent to the address successfully. From the senders point of view it's not possible to distinguish these two cases.
When the server recovers this leaves the client in a difficult situation. It knows the target server failed, but it does not know if the last message reached its destination ok. If it decides to resend the last message, then that could result in a duplicate message being sent to the address. If each message was an order or a trade then this could result in the order being fulfilled twice or the trade being double booked. This is clearly not a desirable situation.
Sending the message(s) in a transaction does not help out either. If the server or connection fails while the transaction commit is being processed it is also indeterminate whether the transaction was successfully committed or not!
To solve these issues Apache ActiveMQ Artemis provides automatic duplicate messages detection for messages sent to addresses.
See more details about how to configure and use duplicate detection in the ActiveMQ Artemis documentation.

Which timeout has TIBCO EMS while waiting for acknowledge?

We are developing a solution using TIBCO-EMS, and we have a question about its behaviour.
When using CLIENT_ACKNOWLEDGE mode to connect, the client acknowledges the received message. We'd like to know for how long does TIBCO wait for acknowledgement, and if this time is configurable by the system admin.
By default, the EMS server waits forever for the acknowledgement of the message.
As long as the session is still alive, the transaction will not be discarded and the server waits for an acknowledgement or rollback.
There is however a setting within the server disconnect_non_acking_consumers where the client will be disconnected, if there are more pending messages (not acknowledged) then the queue limit does allow to store (maxbytes, maxmsgs). In this case, the server sends a connection reset to get rid of the client.
Sadly the documentation doesn't state this explicitly and the only public record I found was a knowledge base entry: https://support.tibco.com/s/article/Tibco-KnowledgeArticle-Article-33925

Watson IoT QoS1/2 Retries

Does anyone know what the Watson IoT broker does if publishes a QoS1 o 2 message and doesn't receive the appropriate acknowledgement from the client? Does it implement a time out (say 20 seconds or so) and then resend the message again? It seems that some brokers do this while others only resend the message on a new connection (if retain is set to 1 of course). The MQTT spec is a little vague on this point.
the message would be considered in-flight for the client that hasn’t acknowledged it, and that message redelivery will only occur when that client disconnects and reconnects (but only if the client was clean session = 0)
For QoS1 and 2:
At least once (QoS1)
With quality of service level 1 (QoS1), the message is always delivered at least once. If a failure occurs before an acknowledgment is received by the sender, a message can be delivered multiple times. The message must be stored locally at the sender until the sender receives confirmation that the message was published by the receiver. The message is stored in case the message must be sent again.
Exactly once (QoS2)
The "exactly once" quality of service level 2 (QoS2) is the safest, but slowest mode of transfer. The message is always delivered exactly once and must also be stored locally at the sender, until the sender receives confirmation that the message was published by the receiver. The message is stored in case the message must be sent again. With quality of service level 2, a more sophisticated handshaking and acknowledgment sequence is used than for level 1 to ensure that messages are not duplicated
MQTT keep alive interval
The MQTT keep alive interval, which is measured in seconds, defines the maximum time that can pass without communication between the client and broker. The MQTT client must ensure that, in the absence of any other communication with the broker, a PINGREQ packet is sent. The keep alive interval allows both the client and the broker to detect that the network failed, resulting in a broken connection, without needing to wait for the TCP/IP timeout period to be reached.
If your Watson IoT Platform MQTT clients use shared subscriptions, the keep alive interval value can be set only to between 1 and 3600 seconds. If a value of 0 or a value that is greater than 3600 is requested, the Watson IoT Platform broker sets the keep alive interval to 3600 seconds.
Retained messages
Watson IoT Platform provides limited support for the retained messages feature of MQTT messaging. If the retained message flag is set to true in an MQTT message that is sent from a device, gateway, or application to Watson IoT Platform, the message is handled as an unretained message. Watson IoT Platform organizations are not authorized to publish retained messages. The Watson IoT Platform service overrides the retained message flag when it is set to true and processes the message as if the retained message flag is set to false.

Resend behavior in MQ Light

I am experimenting with assured delivery in MQ Light.
I am using Node-RED with a modified mqlight input node. I have added the following options the the subscribe() call:
qos: mqlight.QOS_AT_LEAST_ONCE, autoConfirm: false, ttl: (60 * 60 * 24 * 1000)
This requires that I call delivery.message.confirmDelivery() to acknowledge to MQ Light the receipt of the message.
The screenshot below is when the subscription from mqlight_NodeREDClient is set up with autoConfirm false, a message was received, BUT no delivery.message.confirmDelivery() was called. This was to simulate some sort of error occuring in the Node-RED flow.
I have since modified the Node-RED flow to do a confirmDelivery(), and any messages consumed by the flow now are acknowledged OK, even if Node-RED isn't running at the time of publish. The message is held by MQ Light since there is a TTL on the destination and arrives as soon as i start up Node-RED again.
However, the message in this screenshot, which has been sent once already but never confirmed, is never resent. A restart of Node-RED does not change this, the message is still pending. What are the criteria that needs to be fulfilled in order for MQ Light to retransmit a message already sent before but never confirmed by a client?
If you hadn't restarted NodeRED I'd say that it was because MQ Light won't redeliver to a connected client because it thinks the client is still processing the message. However since you have it must be something else.
I've just tried the same basic setup (without NodeRED) and the behaviour is as you'd expect - when you reconnect the receiving client MQ Light redelivers the message and the MQ Light UI ticks it off.
The remaining things I can think of are:
Is it possible when that particular message was sent you had a QoS 0
subscription?
What TTL are you setting on the message at the sender?
What destination TTL have you set on your subscribe call?
If 2. is too low, the message will have been expired from the destination regardless of the QoS of the subscriber or the value of 3.
If 3. is too low and NodeRED was stopped for long enough, the entire destination will have been expired.

Message send timeout for producer sending message to ActiveMQ broker

Is there a way to set timeout for sending a message to broker.
I want to send large messages to ActiveMQ broker but I do not want it to take forever, so I was planning to set a timeout while sending message.
you can set connection.sendTimeout=some ms in URI while connecting to broker
Official document for sendTimeout says
Time to wait on Message Sends for a Response, default value of zero
indicates to wait forever. Waiting forever allows the broker to have
flow control over messages coming from this client if it is a fast
producer or there is no consumer such that the broker would run out
of memory if it did not slow down the producer. Does not affect Stomp
clients as the sends are ack'd by the broker. (Since ActiveMQ-CPP
2.2.1)
here is the documentation https://activemq.apache.org/components/cms/configuring
hope this helps!
Good luck!

Resources