Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Acknowledged delivery: semantics #764

Open
oberstet opened this issue Nov 30, 2016 · 9 comments
Open

Acknowledged delivery: semantics #764

oberstet opened this issue Nov 30, 2016 · 9 comments

Comments

@oberstet
Copy link
Contributor

What semantics should "acknowledged event delivery" have?

An EVENT is to be answered by EVENT_RECEIVED

  1. .. as soon as the event was received (that is potentially even before the user subscription handler fires)
  2. .. after the user subscription handler has ended (regardless whether that user code did raise or not)
  3. .. after the user subscription handler has ended - but only if it ended successfully
  4. .. after the user subscription handler has ended - and the EVENT_RECEIVED contains a flag indicating the success/failure of the user subscription handler

Depending on what we chose for above (what semantics does MQTT has?), we then might want to change the name of the new WAMP message (EVENT_DELIVERED, EVENT_PROCESSED)

@oberstet
Copy link
Contributor Author

oberstet commented Dec 1, 2016

The code that needs to be touched is here

@hawkowl
Copy link
Contributor

hawkowl commented Dec 1, 2016

So, as far as I see it:

4, I think, doesn't have much use (what does the router do with the message? Does it forward it to the original publisher? What would the publisher then do with it?).

3, I feel, mixes up user code and the WAMP transport. WAMP is responsible for getting your messages there, but I don't think it should care about whether the subscription handler was successful. Again, I'm not sure what it would do -- would the router resend it if it failed? It will probably just make code that isn't written entirely transactionally do bad things. Also, what if the subscription handler never finishes, or finishes in a long time comparatively for QoS?

2 has the same problem about long running things.

1, I think, is the way to go. It follows the semantics of other protocols in that QoS is entirely the transport responsibility and not the application responsibility. MQTT, for example, uses it for transferring 'responsibility' from point to point, it does not take into account what the application on the other end does with it. I think this is the most obvious, as it doesn't bring into the question what a failure means to WAMP -- an Exception could be totally reasonable, and we don't want the QoS resending a packet that is valid on the transport, received on the other end, but is invalid according to the semantics of the application. It is, coincidentally, also the simplest -- you send a EVENT_RECEIVED immediately, so there is low latency (lowering the risk of duplicated packets if the connection goes down in the middle), and it removes the question of what we do on failure (we simply log it as we do already) and what happens if the event handler never ends (doesn't matter, as the ACK has been sent already). It also makes it similar to how QoS2 will have to work -- because there are 2 RTs instead of 1, we then don't have to decide when we send each part of the QoS -- we simply do it as it is received.

@goeddea
Copy link

goeddea commented Dec 1, 2016

I agree with @hawkowl that all WAMP should care about is getting the event there. What happens inside the user code is not our concern, and we shouldn't go there. Acknowledgement that components have successfully executed code based on a received subscription are an application-level concern. This will often involve more than just the subscription handler executing without an error, and components other than the publisher may be the ones concerned with the outcome.

@oberstet
Copy link
Contributor Author

oberstet commented Dec 1, 2016

Ok, agreed: PUBLISH/PUBLISHED and EVENT/EVENT_RECEIVED, the latter with the semantics 1) is appropriate and sufficient for QoS 1 (but not QoS 2!).

QoS 2 needs to tie into the app code to achieve the two-phase commit, transactional semantics. Eg think about receiving a "charge event" that deducts money from an account. You want to process such events exactly once, where "exactly once" extends right into the transactional database. A client that really does QoS 2 will need a local persistent storage (better database).

I also think EVENT_RECEIVED is appropriately named. QoS 1 is one mode of assured delivery. QoS 2 another. I have to re-read the MQTT spec parts to see if it is really "transactional messaging" in the hardcore, ACID database sense (there are transactional messaging system .. I just don't know if MQTT is one of them).

@oberstet
Copy link
Contributor Author

oberstet commented Dec 1, 2016

Do we have QoS mode option for SUBSCRIBE already? I mean in AB, like in message.SUBSCRIBE.options? We need that too ..

@oberstet
Copy link
Contributor Author

oberstet commented Dec 1, 2016

The relevant MQTT spec section about QoS is here

@oberstet
Copy link
Contributor Author

oberstet commented Dec 1, 2016

In particular, this:

Figure 4.2 – QoS 1 protocol flow diagram, non normative example
Initiate onward delivery of the Application Message (1)

and the footnote:

(1) The receiver is not required to complete delivery of the Application Message before sending the PUBACK. When its original sender receives the PUBACK packet, ownership of the Application Message is transferred to the receiver.


"complete delivery of the Application Message": I read that as that we do not have to wait for the user code subscription handler to finish - we may do so (it does not say MUST NOT), but why should we? ;)

So think what we agreed to in above for QoS 1 is in line with MQTT QoS 1 semantics.


Interestingly, the MQTT spec has this footnote for QoS 2:

Figure 4.3 – QoS 2 protocol flow diagram, non normative example
The receiver is not required to complete delivery of the Application Message before sending the PUBREC or PUBCOMP. When its original sender receives the PUBREC packet, ownership of the Application Message is transferred to the receiver.

This means, MQTT can not be used for full blown ACID compliant transactional messaging. Which is good, because that would require to make a 2-phase-commit, distributed transaction manager (integrated down to the protocol) available/accesible at the app layer. Which not only sounds complex, but is complex;)

@oberstet
Copy link
Contributor Author

oberstet commented Dec 1, 2016

Btw, in case you wonder about the answer to this question: "MQTT - QoS - what does TCP not provide which MQTT does?"

I think this is a question that naturally arises, and the question is formulated nicely.

The answer is in the spec:

4.4 Message delivery retry

When a Client reconnects with CleanSession set to 0, both the Client and Server MUST re-send any unacknowledged PUBLISH Packets (where QoS > 0) and PUBREL Packets using their original Packet Identifiers [MQTT-4.4.0-1]. This is the only circumstance where a Client or Server is REQUIRED to redeliver messages.

and here

Non normative comment
Historically retransmission of Control Packets was required to overcome data loss on some older TCP networks. This might remain a concern where MQTT 3.1.1 implementations are to be deployed in such environments.


That means, we don't need any timers or such (because TCP takes care). It also means: without session resumption, both QoS 1 and 2 are void.

@oberstet
Copy link
Contributor Author

oberstet commented Dec 1, 2016

overcome data loss on some older TCP networks

I am really wondering what they are talking about here. TCP is reliable regardless of underlying OSI 1/2 tech. So there is no "data loss" to overcome .. on what "older TCP networks".

I don't get that part.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants