Background
mproxy's Handler interface exposes hooks for CONNECT, PUBLISH, SUBSCRIBE, UNSUBSCRIBE, and DISCONNECT. For QoS2 flows, the full 4-step handshake between broker and client is invisible to the handler — packets either fall through notify's default case (upstream) or notify is never called at all (downstream).
This makes it impossible to track per-device, per-message delivery state at the application level.
QoS2 flow (broker → device):
broker → device : PUBLISH (downstream — no hook)
device → broker : PUBREC (upstream — falls through notify)
broker → device : PUBREL (downstream — no hook)
device → broker : PUBCOMP (upstream — falls through notify)
Proposal
Extend the Handler interface with four new hooks:
// PubSent is called when broker dispatches a QoS2 PUBLISH to a client.
PubSent(client *Client, packetID uint16, topic string)
// PubReceived is called when a client sends PUBREC.
PubReceived(client *Client, packetID uint16)
// PubRelease is called when broker sends PUBREL to a client.
PubRelease(client *Client, packetID uint16)
// PubComplete is called when a client sends PUBCOMP.
PubComplete(client *Client, packetID uint16)
Wire in session.go:
// upstream (notify)
case *packets.PubrecPacket:
s.handler.PubReceived(&s.Client, p.MessageID)
case *packets.PubcompPacket:
s.handler.PubComplete(&s.Client, p.MessageID)
// downstream (new notifyDown)
case *packets.PublishPacket:
s.handler.PubSent(&s.Client, p.MessageID, p.TopicName)
case *packets.PubrelPacket:
s.handler.PubRelease(&s.Client, p.MessageID)
Use Case
Full per-device, per-message delivery lifecycle:
| Step |
Direction |
Hook |
Meaning |
| 1 |
broker → device |
PubSent |
Message dispatched |
| 2 |
device → broker |
PubReceived |
Device acknowledged receipt |
| 3 |
broker → device |
PubRelease |
Broker releasing |
| 4 |
device → broker |
PubComplete |
Device confirmed delivery ✓ |
State stored keyed by clientID:packetID, exposable via API or event stream — no application-level ACK topic needed.
Breaking Change
Breaking change to the Handler interface. All existing implementations must add the four new methods.
Background
mproxy's
Handlerinterface exposes hooks forCONNECT,PUBLISH,SUBSCRIBE,UNSUBSCRIBE, andDISCONNECT. For QoS2 flows, the full 4-step handshake between broker and client is invisible to the handler — packets either fall throughnotify's default case (upstream) ornotifyis never called at all (downstream).This makes it impossible to track per-device, per-message delivery state at the application level.
QoS2 flow (broker → device):
Proposal
Extend the
Handlerinterface with four new hooks:Wire in
session.go:Use Case
Full per-device, per-message delivery lifecycle:
PubSentPubReceivedPubReleasePubCompleteState stored keyed by
clientID:packetID, exposable via API or event stream — no application-level ACK topic needed.Breaking Change
Breaking change to the
Handlerinterface. All existing implementations must add the four new methods.