eclipse / paho.mqtt-sn.embedded-c

Paho C MQTT-SN gateway and libraries for embedded systems. Paho is an Eclipse IoT project.
https://eclipse.org/paho
Other
315 stars 178 forks source link

Message loss for subscribed topics after gateway restart #134 #135

Closed simon-ebner closed 6 years ago

ty4tw commented 6 years ago

Hi Simon, How do you handle about pre-defined-topic?

simon-ebner commented 6 years ago

Hi Tomoaki,

yeah pre-defined topics would also be a solution, but it has the drawback that you have to maintain a possibly large configuration list of all pre-defined topics.

In the area of IoT devices with topics structures that could change over time from version to version this could lead to a configuration hell.

Fortunately the pre-defined topic implementation is now more flexible than before thanks to your improvement regarding issue: https://github.com/eclipse/paho.mqtt-sn.embedded-c/issues/132 This change made it possible to map an arbitrary client ID with a certain pre-defined topic id to the defined long name without having to device that id in the configuration list which is nice as it doesn't require a pre-commissioning process of new clients and you don't have to restart your gateway to load the new definitions.

If we would solve that issue with the concept of pre-defined topic you then have to restart the gateway and exactly this scenario leads to message loss which gets fixed by this pull request.

Another drawback of pre-defined topics is the following: You can't partition pre-defined topics by client id. The mapping does only hold for common / shared topic. Let assume we use the new Wildcard definition like the following one:

Sample pre-defined topics configuration: *,/a,1

If Client_1 subscribes to pre-defined topic 1 then there's a mapping to topic /a If Client_2 subscribes to pre-defined topic 1 then there's also a mapping to topic /a

But how to define a pre-defined topic where the mapping looks like that: If Client_1 subscribes to pre-defined topic 1 then there's a mapping to topic /Client_1/a If Client_2 subscribes to pre-defined topic 1 then there's also a mapping to topic /Client_2/a

We then somehow need both concepts expressed in a configuration file where you can additionally specify whether it is a common topic or a client partitioned topic where you have the client id as prefix in the long topic name mapping. But this doesn't solve the problem that you have to restart your gateway.

There are scenarios which require dynamic topic registrations or concepts were a client that connects to a new gateway always first registers the topics it like to use in its communication. This has only to be performed once since the subscriptions are stored on the broker side.

When then the client connects to another gateway since the other may have failed then you don't want to loose messages as described in that issue.

What do you think about the extension of the pre-defined topic concept in future?

ty4tw commented 6 years ago

Hi,

What I want to say is PR can not handle the pre-defined-topic and same of clients can not handle the REGISTER message. I think in this case, clean session might be the solution.

Tomoaki YAMAGUCHI

2018-09-06 22:54 GMT+09:00 Simon Ebner notifications@github.com:

Hi Tomoaki,

yeah pre-defined topics would also be a solution, but it has the drawback that you have to maintain a possibly large configuration list of all pre-defined topics.

In the area of IoT devices with topics structures that could change over time from version to version this could lead to a configuration hell.

Fortunately the pre-defined topic implementation is now more flexible than before thanks to your improvement regarding issue: #132 https://github.com/eclipse/paho.mqtt-sn.embedded-c/issues/132 This change made it possible to map an arbitrary client ID with a certain pre-defined topic id to the defined long name without having to device that id in the configuration list which is nice as it doesn't require a pre-commissioning process of new clients and you don't have to restart your gateway to load the new definitions.

If we would solve that issue with the concept of pre-defined topic you then have to restart the gateway and exactly this scenario leads to message loss which gets fixed by this pull request.

Another drawback of pre-defined topics is the following: You can't partition pre-defined topics by client id. The mapping does only hold for common / shared topic. Let assume we use the new Wildcard definition like the following one:

Sample pre-defined topics configuration: *,/a,1

If Client_1 subscribes to pre-defined topic 1 then there's a mapping to topic /a If Client_2 subscribes to pre-defined topic 1 then there's also a mapping to topic /a

But how to define a pre-defined topic where the mapping looks like that: If Client_1 subscribes to pre-defined topic 1 then there's a mapping to topic /Client_1/a If Client_2 subscribes to pre-defined topic 1 then there's also a mapping to topic /Client_2/a

We then somehow need both concepts expressed in a configuration file where you can additionally specify whether it is a common topic or a client partitioned topic where you have the client id as prefix in the long topic name mapping. But this doesn't solve the problem that you have to restart your gateway.

There are scenarios which require dynamic topic registrations or concepts were a client that connects to a new gateway always first registers the topics it like to use in its communication. This has only to be performed once since the subscriptions are stored on the broker side.

When then the client connects to another gateway since the other may have failed then you don't want to loose messages as described in that issue.

What do you think about the extension of the pre-defined topic concept in future?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/eclipse/paho.mqtt-sn.embedded-c/pull/135#issuecomment-419101353, or mute the thread https://github.com/notifications/unsubscribe-auth/AHd9BHivMXATFNnEbeMz3i69V8TJb11qks5uYSj5gaJpZM4Wc32z .

simon-ebner commented 6 years ago

Hey, could you please shortly describe a situation where we would have a breaking change that hasn't been before?

In which circumstances can a client not handle a REGISTER message? Are you thinking about conflicting ids?

Simon

ty4tw commented 6 years ago

Hi, Situation is Client SUBSCRIBE with pre-defined-topicId. e.g. ID=1, ID type=pre-defined convert to Topic=a/b/c
GW restart and recevie PUBLISH message of a/b/c GW doesn't know a/b/c is a normal or pre-defined type. GW assumes normal then send REGISTER Client is not implemented REGISTER procedure. because it sends only pre-defined-topic.

Are you thinking about conflicting ids?

Your presupposition is "re-subscribes without clean session after the gateway has been restarted" My idea is Clients which subscribe topics should CONNECT with clean session.

simon-ebner commented 6 years ago

Hi, thanks for your great explanation. Indeed we can't distinguish between both topic types and don't know whether we should send the REGISTER command form the gateways side. But as the list of pre-defined topics should be known to both sides we could say that further logic is up to the client. It's legitimate for the client to ignore a REGISTER command which contains a topic that is already known to itself - and to the gateway. If not the client is able to receive the mapping from short topic id to the long topic name for the message that will be delivered right after the REGISTER has been confirmed from the client.

Could we stick with that?

ty4tw commented 6 years ago

Hi Simon, I'm happy to discuss about this matter. Thank you for your contribution.

Could we stick with that?

We should not to change the code, if you want to ignore the pre-defined-topic.

that will be delivered right after the REGISTER has been confirmed from the client.

When the client can't return the REGACK because of not implemented, the Broker retry to send PUBLIC in case of QoS1 or 2. GW have to judge disposing the PUBLISH message soon or later. we need add this procedure to the GW. It will not be a simple.

So in this case, "Clients which subscribe topics should CONNECT with clean session" should be a final solution. Because the Client can easily SUBSCRIBE again after CONNECT message without any additional code. It's enough to set the CONNECT's clean session flag bit to 1. Simple is the BEST is my design's principle.

Do you stick to the "without clean session"? If you do, I'd like to know your situation. why you can't send a CONNECT with clean session flag?

simon-ebner commented 6 years ago

Thanks for your valuable discussion & contribution as well, Tomoaki!

Assume that you have an infrastructure that consists of the following topology: Client <- MQTT-SN -> MQTT-SN Gateway <- TCP -> MQTT-CLUSTER <- MQTT -> Backend Service

When we talk with QoS 2 from device to the service and vice-versa then we don't want to loose information and data must be delivered exactly once - no matter whether you're using regular topic registration or the concept of pre-defined topics. To even ensure in order transmission one has to send messages with a max inflight size of 1. For ordered topics having available we even don't wan't to mess up this feature.

When there's a MQTT cluster that supports enterprise features like fail-over and message persistence then we also don't want to soften up this requirement as we loose data in the scenario where we simply restart the MQTT-SN gateway in front of the broker.

I think it's worth to investigate such quality goals and to make appropriate contributions.

Could you please briefly tell me what other logic may be missing on the clients side?

For all my tests I directly used the samples from the UDP directory. I also tried to directly communicate via pre-defined topics in a test scenario which didn't work as expected. There's no bare subscriber sample code which directly subscribes to a pre-defined topic. There's just a sample that first registers a long name topics, gets a short topic id, publishes and then receives such a message via subscription.

I would appreciate if one of us could make a proper contribution.

Please keep me updated.

Simon

ty4tw commented 6 years ago

Anyway, it’s a time to close this pull request