Will that be a node-red build? I haven't done that, but I think it is documented somewhere so can probably work it out with a small amount of guidance.
I see from the HiveMQ videos that MQTT v5 offers other new features that could be valuable to Node-red, eg shared subscriptions, enhanced authentication, user properties.
Will this new node support these features too? No idea how much coding beyond extra config options would be needed!
Will install node-red source in ~/src/node-red change as required
mkdir ~/src
cd ~/src
git clone git@github.com:node-red/node-red.git
cd node-red
git switch feat-mqtt-request
npm ci
npm run dev
If you already have a node-red instance running locally, you can start with parameters like this: npm run dev -- --userDir "~/.node-red-1881" --port 1881
Configure the node to connect to a broker on a different machine, where one can pull the ethernet cable from the node red machine (or otherwise break the connection). Leave timeout at 5 seconds
Add Catch and Complete nodes
Build the response flow on the remote machine
Test it works, obviously.
Pull the cable
Before the node shows disconnected (which is about a minute on my system) post a couple of requests
The messages passed in, but not sent, do not generate timeout errors in the Catch node
Wait for the node to show Disconnected and plug the cable back in
When the node connects again then valid responses are emitted, even though the timeout is long gone.
Do you mean successful publish? Is it not permanently subscribed?
I don't understand the logic, if you have slow comms then you can increase the timeout.
In my use case (guaranteed delivery of messages) I send one message at a time and wait for Complete or Timeout. If it Completes then I send the next one, if it times out then I wait a bit and try again. However, I need to impose a 'super timeout' in the flow that forces a retry if I don't see any response from the node after some time. That is to prevent lockup due to a lost message such as can occur in a partial deploy for example. So I need to know that if I wait long enough then I can be sure that the message is lost. With the current code it seems there is no way of knowing for certain that the message is not going to suddenly generate a Complete message hours later when the network recovers
I don't see what advantage there is in waiting before starting the timeout. Certainly it is not what I expected.
I do need the timeout to work from when the message is posted however. Otherwise I think I will have to put back several of the nodes in my original flow, provide my own correlation data, and check each message as it comes back to make sure it is from the most recent message.
That depends on the qos (qos 0 is fire and forget)
Yes, if it's a static response topic. No if it is passed in the msg (dynamic response topic).
If you do get an error during subscription, it will throw a catchable error.
There is a grey area tho - in a half open connection state (like you describe) - the (existing) behaviour of the mqtt client we use is that if you manage to catch it, the message gets queued by the internal store. Upon connect it's delivered. This is shared behaviour across the mqtt nodes and changing that will change existing behaviours.
I do add a v5 message expiry value to the packet but that is (strictly speaking) a broker implementation so late delivery may or may not be rejected depending on the broker. (Not sure how mqtt.js handles these, but to be clear, the behaviour is broker specific not client specific)
Another caveat is if I DO start the timeout BEFORE subscription & it is delayed/slow subscribing (such that the message reaches the client but the node times out before the response arrives) is that you won't know (or rather think it failed) so a non idempotent receiver action would be triggered again when you do a resend.
All that said, you do make some valid points and so I have updated the MQTT Request PR to do the following:
before reading the bullets, I have (hopefully) made this clear in the built-in help - the points below are in case i didnt do a good job of that
The timeout now runs end-to-end - it starts the moment the message arrives and covers the whole exchange (subscribe → publish → waiting for the reply). So you always get one outcome within the timeout: either a response on the output, or an error, even if the connection is half-open and the subscribe/publish stalls.
On timeout, the error tells you what actually happened. The (catchable) error message distinguishes "delivered but no response" from "not confirmed delivered", and the outgoing msg carries a small flag object:
delivered is true when publishing was confirmed before we gave up - for QoS 1/2 that means the broker acknowledged it; for QoS 0 it only means it was written to the connection.
If it gives up on a QoS 1/2 request that was never acknowledged, it is now purged from the client's outgoing store so that it isn't silently retransmitted on reconnect. i.e. the "queued by the internal store, delivered on connect" behaviour you flagged. It will only do this while it's still unacknowledged; once it's been acked there's nothing to purge and so leave the store alone. The v5 message-expiry value is still set as the broker-side backstop
The original message is passed through to the output (and to a Catch node on error) with its non-MQTT properties intact, so it slots into existing flows (http-in req/res, link-call, etc.) without losing context.
What this means to your guaranteed-delivery flows: just wait for the node to emit. Success → send the next one. Error → check msg.mqtt.delivered: false = safe to resend, true = it reached the broker so treat a resend as potentially duplicate. Either way you get a definite answer inside the timeout window, so no lock-up and no need for the external "super timeout".
Please git pull the changes, restart node-red (npm run dev) and test it out:
Yes, it has always been the case that the receiver may receive repeated requests, I don't think there is any way to avoid that. If it is important to the client that repeated requests are ignored then he would have to add a serial number, or similar, to allow detection of this.
Regarding that caveat, I have somewhat mitigated it for QoS 1 and QoS 2 (see the bit about " If it gives up on a QoS 1/2 request that was never acknowledged, it is now purged from the client's outgoing store" & the new flag msg.mqtt.delivered can help a user flow make informed decisions)
This is a difference in behaviour for the new node ONLY. It makes sense because this is about Request - Response specifically.
Please continue do to test and evaluate & let me know if there is any issues or subtleties to address before it becomes mainstream (assuming it is accepted of course)
Yes, I am continuing to test. Dynamic topics seem to be working ok.
Having made yourself familiar again with the MQTT node, is there a chance that you could look at this existing issue? It would be useful to me, and I suspect it would be a simple change.
Only implementation time. If the need for all bells and whistles is raised in review as a blocker, then the PR will either sit and wait for the extra work to get done or worse, it doesnt get done and doesnt get merged. As a first implementation, this is fairly feature complete (as a request response node) and there is nothing stopping tasks being raised for later follow up.