2
I Use This!
High Activity

News

Analyzed about 17 hours ago. based on code collected 1 day ago.
Posted about 5 years ago
Motivation Ditto 1.2.0 introduced at-least-once delivery via acknowledgement requests. It increased coupling between the publisher and the subscriber of signals in that the subscriber is no longer at the liberty to filter for signals it is ... [More] interested in. Instead, the subscriber must consume all signals in order to fulfill acknowledgement requests and prevent endless redelivery. To combat the problem, Ditto 1.4.0 made acknowledgement labels unique and introduced the requirement to manage declared acknowledgements, identifying of each subscriber. It is now possible for Ditto to issue weak acknowledgements on behalf of the subscriber whenever it decides to not consume a signal. That allows subscribers to configure RQL and namespace filters freely without causing any futile redelivery. Note: Weak acknowledgements are available since Ditto 1.5.0. What it is A weak acknowledgement is issued by Ditto for any acknowledgement request that will not be fulfilled now or ever without configuration change. A weak acknowledgement is identified by the header ditto-weak-ack: true. The status code of weak acknowledgements is 200 OK; it signifies that any redelivery is not to be made on their account. A weak acknowledgement may look like this in Ditto protocol: { "topic": "com.acme/xdk_53/things/twin/acks/my-mqtt-connection:my-mqtt-topic", "headers": { "ditto-weak-ack": true }, "path": "/", "value": "Acknowledgement was issued automatically, because the subscriber is not authorized to receive the signal.", "status": 200 } How it works Since Ditto 1.4.0, subscribers of twin events or live signals are required to declare unique acknowledgement labels they are allowed to send. The labels of acknowledgement requests are then identifying the intended subscribers. If the intended subscriber exists but does not receive the signal for non-transient reasons, Ditto issues a weak acknowledgement for that subscriber. Such reasons may be: The intended subscriber is not authorized to receive the signal by policy; The intended subscriber did not subscribe for the signal type (twin event, live command, live event or live message); The intended subscriber filtered the signal out by its namespace or RQL filter; The intended subscriber dropped the signal because its payload mapper produced nothing. Limitation The distributed nature of cluster pub/sub means that weak acknowledgements are not always issued correctly. They are only eventually correct in the sense that some time after a change to the publisher-subscriber pair, the issued weak acknowledgements will reflect the change. Such changes include: Opening and closing of Websocket or other connections acting as the subscriber; Subscribing and unsubscribing for different signal types via Websocket; Modification of connections via the connectivity API; Migration of a connection from one Ditto cluster member to another due to load balancing. Feedback? Please get in touch if you have feedback or questions towards this new concept of weak acknowledgements. – The Eclipse Ditto team [Less]
Posted about 5 years ago
Desired feature properties added to things model With the release of Eclipse Ditto version 1.5.0 desired feature properties are introduced to the things model for API versions later than 1. The desired properties for features are added on the same ... [More] level of the model as the feature properties and can reflect for example feature property updates ,which are intended, but not yet applied. Further logics for desired feature properties might be implemented in future Ditto versions. A fully-fledged JSON representation of a feature with desired properties is shown below: { "lamp": { "definition": [ "com.mycompany.fb:Lamp:1.0.0" ], "properties": { "configuration": { "on": true, "location": { "longitude": 34.052235, "latitude": -118.243683 } }, "status": { "on": false, "color": { "red": 128, "green": 255, "blue": 0 } } }, "desiredProperties": { "configuration": { "on": false } } } } Operations on desired feature properties CRUD operations You can create multiple desired properties of a feature or just single ones. You can retrieve all desired properties of a feature or just single ones. You can modify all desired properties of a feature or just single ones. You can delete all desired properties of a feature or just single ones. Search You can search for things with specific desired properties with RQL-functions. You can search for things, which have existent desired properties for a feature. Get notified on changes You can receive events for changes done to the desired properties of things you’re authorized to read. You can enrich and filter the events you want to receive, for changes done to the desired properties. Executing CRUD operations on desired feature properties CRUD operations can be executed either via the Ditto HTTP API versions later than 1 or via ditto-protocol messages. Possible CRUD operations for desired feature properties via ditto-protocol: Retrieve all desired properties of a feature via ditto-protocol Retrieve a single desired property of a feature via ditto-protocol Create/Modify all desired properties of a feature via ditto-protocol Create/Modify a single desired property of a feature via ditto-protocol Delete all desired properties of a feature via ditto-protocol Delete a single desired property of a feature via ditto-protocol Using the ditto-client to manage desired feature properties The desired feature properties can also be retrieved, modified and deleted via the Ditto Java Client. At the time of publishing of this blog post (Ditto Java Client version 1.5.0), no special CRUD operations for desired feature properties are implemented in the client. Thus, the operations have to be executed via creating ditto-protocol messages manually in the client. Example for creating/modifying desired feature properties of a thing via the ditto-client: final Adaptable modifyFeatureDesiredProperties = Adaptable.newBuilder(TopicPath.newBuilder(ThingId.of("com.mycompany.fb:Car:1.0.0")) .things() .twin() .commands() .modify() .build()) .withPayload(Payload.newBuilder( JsonPointer.of("/features/lamp/desiredProperties")) .withValue(JsonObject.newBuilder().set("on", false).build()) .build()).build(); client.sendDittoProtocol(modifyFeatureDesiredProperties).whenComplete(((adaptable, throwable) -> { if (throwable != null) { LOGGER.error("Received error while sending ModifyFeatureDesiredProperties: '{}' ", throwable.toString()); } else { LOGGER.info("Received response for ModifyFeatureDesiredProperties: '{}'", adaptable); } })); – The Eclipse Ditto team [Less]
Posted about 5 years ago
Desired feature properties added to things model With the upcoming release of Eclipse Ditto version 1.5.0 desired feature properties are introduced to the things model for API versions later than 1. The desired properties for features are added on ... [More] the same level of the model as the feature properties and can reflect for example feature property updates ,which are intended, but not yet applied. Note: Further logics for desired feature properties might be implemented in future Ditto versions. A fully-fledged JSON representation of a feature with desired properties is shown below: { "lamp": { "definition": [ "com.mycompany.fb:Lamp:1.0.0" ], "properties": { "configuration": { "on": true, "location": { "longitude": 34.052235, "latitude": -118.243683 } }, "status": { "on": false, "color": { "red": 128, "green": 255, "blue": 0 } } }, "desiredProperties": { "configuration": { "on": false } } } } Operations on desired feature properties CRUD operations You can create multiple desired properties of a feature or just single ones. You can retrieve all desired properties of a feature or just single ones. You can modify all desired properties of a feature or just single ones. You can delete all desired properties of a feature or just single ones. Search You can search for things with specific desired properties with RQL-functions. You can search for things, which have existent desired properties for a feature. Get notified on changes You can receive events for changes done to the desired properties of things you’re authorized to read. You can enrich and filter the events you want to receive, for changes done to the desired properties. Executing CRUD operations on desired feature properties CRUD operations can be executed either via the Ditto HTTP API versions later than 1 or via ditto-protocol messages. Possible CRUD operations for desired feature properties via ditto-protocol: Retrieve all desired properties of a feature via ditto-protocol Retrieve a single desired property of a feature via ditto-protocol Create/Modify all desired properties of a feature via ditto-protocol Create/Modify a single desired property of a feature via ditto-protocol Delete all desired properties of a feature via ditto-protocol Delete a single desired property of a feature via ditto-protocol Using the ditto-client to manage desired feature properties The desired feature properties can also be retrieved, modified and deleted via the Ditto Java Client. With the upcoming (Ditto Java Client version 1.5.0), no special CRUD operations for desired feature properties are implemented in the client. Thus, the operations have to be executed via creating ditto-protocol messages manually in the client. Example for creating/modifying desired feature properties of a thing via the ditto-client: final Adaptable modifyFeatureDesiredProperties = Adaptable.newBuilder(TopicPath.newBuilder(ThingId.of("com.mycompany.fb:Car:1.0.0")) .things() .twin() .commands() .modify() .build()) .withPayload(Payload.newBuilder( JsonPointer.of("/features/lamp/desiredProperties")) .withValue(JsonObject.newBuilder().set("on", false).build()) .build()).build(); client.sendDittoProtocol(modifyFeatureDesiredProperties).whenComplete(((adaptable, throwable) -> { if (throwable != null) { LOGGER.error("Received error while sending ModifyFeatureDesiredProperties: '{}' ", throwable.toString()); } else { LOGGER.info("Received response for ModifyFeatureDesiredProperties: '{}'", adaptable); } })); Feedback? Please get in touch if you have feedback or questions towards this new concept of desired properties. – The Eclipse Ditto team [Less]
Posted about 5 years ago
Desired feature properties added to things model With the upcoming release of Eclipse Ditto version 1.5.0 desired feature properties are introduced to the things model for API versions later than 1. The desired properties for features are added on ... [More] the same level of the model as the feature properties and can reflect for example feature property updates ,which are intended, but not yet applied. Note: Further logics for desired feature properties might be implemented in future Ditto versions. A fully-fledged JSON representation of a feature with desired properties is shown below: { "lamp": { "definition": [ "com.mycompany.fb:Lamp:1.0.0" ], "properties": { "configuration": { "on": true, "location": { "longitude": 34.052235, "latitude": -118.243683 } }, "status": { "on": false, "color": { "red": 128, "green": 255, "blue": 0 } } }, "desiredProperties": { "configuration": { "on": false } } } } Operations on desired feature properties CRUD operations You can create multiple desired properties of a feature or just single ones. You can retrieve all desired properties of a feature or just single ones. You can modify all desired properties of a feature or just single ones. You can delete all desired properties of a feature or just single ones. Search You can search for things with specific desired properties with RQL-functions. You can search for things, which have existent desired properties for a feature. Get notified on changes You can receive events for changes done to the desired properties of things you’re authorized to read. You can enrich and filter the events you want to receive, for changes done to the desired properties. Executing CRUD operations on desired feature properties CRUD operations can be executed either via the Ditto HTTP API versions later than 1 or via ditto-protocol messages. Possible CRUD operations for desired feature properties via ditto-protocol: Retrieve all desired properties of a feature via ditto-protocol Retrieve a single desired property of a feature via ditto-protocol Create/Modify all desired properties of a feature via ditto-protocol Create/Modify a single desired property of a feature via ditto-protocol Delete all desired properties of a feature via ditto-protocol Delete a single desired property of a feature via ditto-protocol Using the ditto-client to manage desired feature properties The desired feature properties can also be retrieved, modified and deleted via the Ditto Java Client. With the upcoming (Ditto Java Client version 1.5.0), no special CRUD operations for desired feature properties are implemented in the client. Thus, the operations have to be executed via creating ditto-protocol messages manually in the client. Example for creating/modifying desired feature properties of a thing via the ditto-client: final Adaptable modifyFeatureDesiredProperties = Adaptable.newBuilder(TopicPath.newBuilder(ThingId.of("com.mycompany.fb:Car:1.0.0")) .things() .twin() .commands() .modify() .build()) .withPayload(Payload.newBuilder( JsonPointer.of("/features/lamp/desiredProperties")) .withValue(JsonObject.newBuilder().set("on", false).build()) .build()).build(); client.sendDittoProtocol(modifyFeatureDesiredProperties).whenComplete(((adaptable, throwable) -> { if (throwable != null) { LOGGER.error("Received error while sending ModifyFeatureDesiredProperties: '{}' ", throwable.toString()); } else { LOGGER.info("Received response for ModifyFeatureDesiredProperties: '{}'", adaptable); } })); Feedback? Please get in touch if you have feedback or questions towards this new concept of desired properties. – The Eclipse Ditto team [Less]
Posted about 5 years ago
Today, the Ditto team is happy to announce the next feature update of Ditto 1.x: Eclipse Ditto 1.4.0 1.4.0 focuses on: Declaration of acknowledgement labels unique to each subscriber Please have a look at the 1.4.0 release notes for a more ... [More] detailed information on the release. Also, some bugs were fixed which are not backported to Ditto 1.3.0 - it is recommended to update to Ditto 1.4.0 right away and skip 1.3.0. Artifacts The new Java artifacts have been published at the Eclipse Maven repository as well as Maven central. Also the Ditto Java client’s artifacts were published to Maven central. The Docker images have been pushed to Docker Hub: eclipse/ditto-policies eclipse/ditto-things eclipse/ditto-things-search eclipse/ditto-gateway eclipse/ditto-connectivity eclipse/ditto-concierge Kubernetes ready: Helm chart In order to run Eclipse Ditto in a Kubernetes environment, best rely on the official Helm chart and deploy Ditto via the Helm package manager. – The Eclipse Ditto team [Less]
Posted about 5 years ago
Today, the Ditto team is happy to announce the next feature update of Ditto 1.x: Eclipse Ditto 1.4.0 1.4.0 focuses on: Declaration of acknowledgement labels unique to each subscriber Please have a look at the 1.4.0 release notes for a more ... [More] detailed information on the release. Also, some bugs were fixed which are not backported to Ditto 1.3.0 - it is recommended to update to Ditto 1.4.0 right away and skip 1.3.0. Artifacts The new Java artifacts have been published at the Eclipse Maven repository as well as Maven central. Also the Ditto Java client’s artifacts were published to Maven central. The Docker images have been pushed to Docker Hub: eclipse/ditto-policies eclipse/ditto-things eclipse/ditto-things-search eclipse/ditto-gateway eclipse/ditto-connectivity eclipse/ditto-concierge Kubernetes ready: Helm chart In order to run Eclipse Ditto in a Kubernetes environment, best rely on the official Helm chart and deploy Ditto via the Helm package manager. – The Eclipse Ditto team [Less]
Posted about 5 years ago
E2E acknowledgement using Eclipse Ditto By adding the new acknowledgements feature to Ditto, it is now possible to provide an end to end QoS (quality of service) with level 1. Previously the connectivity service of Ditto did accept all incoming ... [More] messages immediately as soon as it received the message. This behaviour can now be controlled by a Ditto header called requested-acks. In this blog post I will provide a few examples for how to use this new feature in the following scenarios: Device publishes a change of its state and doesn’t care about whether the event regarding this change will be received by any subscriber or not. This is the fire and forget scenario. Device publishes a change of its state and wants to be sure it is persisted in Ditto. This is the processed in Ditto scenario. Device publishes a change of its state and wants to be sure an application connected to Eclipse Ditto will receive the event regarding this change of the state. This is the notification scenario. Device publishes a change of its state and wants to be notified when a subscriber was not able to receive the event regarding this change. This is the tracked notification scenario. Device sends a live message and wants to be sure that it will eventually receive a response. This is the long running live message scenario. Device sends a live message and wants to either receive the response within a given timeout or never. This is the asking for required information scenario. Scenarios The following scenarios all share the same context: a device sends data/messages via a device connectivity layer (e.g. Eclipse Hono or an MQTT broker) to Ditto Ditto’s connectivity service consumes the Ditto Protocol message forwards the message into the Ditto cluster to be processed is responsible for technically acknowledging/settling the consumed message at the device connectivity layer / broker the strategy of when this is done and with which outcome is handled by the Ditto headers mentioned in the scenarios Although all scenarios are based on the device sending something (e.g. telemetry data or a message), the E2E acknowledgement can also be used the other way around when e.g. a backend application sends something to a device. Scenario 1 - Fire and Forget This is the simplest scenario of all, since the change can be published in a fire and forget semantics. In this scenario the device will send the modification command containing the headers: response-required=false requested-acks=[] Example Ditto Protocol message: { "topic": "org.eclipse.ditto/my-thing/things/twin/commands/modify", "headers": { "response-required": false, "requested-acks": [] }, "path": "/features/lightSwitch/properties/status", "value": "on" } For this case the connectivity service will immediately acknowledge the incoming message at the messaging system and then continues to process the command. It doesn’t matter if the command could be processed successfully or if any subscriber received an event for this change. Scenario 2 - Processed in Ditto For this scenario the device wants to be sure its change will be properly persisted in Ditto. The command needs to define the following headers: response-required=false requested-acks=["twin-persisted"] Example Ditto Protocol message: { "topic": "org.eclipse.ditto/my-thing/things/twin/commands/modify", "headers": { "response-required": false, "requested-acks": ["twin-persisted"] }, "path": "/features/lightSwitch/properties/status", "value": "on" } For this case the connectivity service will wait until the modification will be properly persisted in Ditto before acknowledging the incoming message at the messaging system. If the device published this command for example via an AMQP broker (with a QoS 1 “at least once” semantic), this will cause the broker to redeliver the command to Ditto if the acknowledgment fails. Please be aware that a redelivery will only be requested for the following error status codes: 408 (Request timed out) 424 (Dependency Failure) All kinds of 5xx status codes In this scenario it does matter if the command could be processed successfully, but it’s still not relevant if any subscriber received an event for this change. Scenario 3 - Notification scenario For this scenario the device wants to be sure another system will be notified about the change of its state. This could be for example an alarming system which wants to be sure a backend application receives the information that the alarm was triggered. A prerequisite for this is that any kind of connection exists that publishes the event to the backend application and declares a user defined acknowledgement label. This can be a WebSocket session or any kind of Ditto Connection types which can be found here. For this example we expect the event to be forwarded by an HTTP connection which declared the following acknowledgement label as issued acknowledgement of the target: d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed. The UUID prefix in this case is the ID of the HTTP connection and thebackend-process part is a custom label, defined by the user. The command needs to define the following headers: response-required=false requested-acks=["d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed"] timeout=30s (optional. Default is 10s.) Example Ditto Protocol message: { "topic": "org.eclipse.ditto/my-thing/things/twin/commands/modify", "headers": { "response-required": false, "requested-acks": ["d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed"], "timeout": "30s" }, "path": "/features/alarm/properties/status", "value": "on" } For this case the connectivity service will wait until the HTTP request, which forwards the event regarding the thing change, will be finished before acknowledging the incoming message at the messaging system. The status code of the HTTP response will in this case determine if the message will be acknowledged successfully or not and if a redelivery will be requested or not. All kinds of 2xx status codes will lead to a successful acknowledgement at the messaging system. All other status codes will lead to a failed acknowledgement at the messaging system and for the following status codes a redelivery will be requested: 408 (Request timed out) 424 (Dependency Failure) All kinds of 5xx status codes In this scenario it is ensured a specified subscriber will receive an event for this change. Scenario 4 - Tracked notification scenario For this scenario the device wants to know when a system could not be notified about the change of its state. This could be for example an alarming system which wants to be sure a backend application receives the information, or if not: tries to send an SMS as notification. This scenario is mostly like scenario 3, but needs to set the response-required header to true and it’s required to configure the reply-target of the source to also expect “nack” responses. Example Ditto Protocol message: { "topic": "org.eclipse.ditto/my-thing/things/twin/commands/modify", "headers": { "response-required": true, "requested-acks": ["d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed"] }, "path": "/features/alarm/properties/status", "value": "on" } In this case the device will receive an acknowledgement response containing the status code and payload of the response of the backend application. Based on this the device can decide how to handle the situation. It is suggested to publish the modification command with QoS 0 (“at most once” semantics) in this case because the device handles the result of the E2E acknowledgement. With QoS 1 (“at least once” semantics) brokers would usually redeliver the message to Ditto. If the HTTP endpoint of the backend application responds with the following response: headers: "content-type": "application/json" body: { "errorCode": "notification.smartphone.failed", "message": "Could not notify smartphone." } status code: 424 The response received at the device would look like this: { "topic": "org.eclipse.ditto/my-thing/things/twin/acks/d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed", "headers": { "response-required": false, "requested-acks": ["d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed"], "timeout": "30s", "content-type": "application/json" }, "path": "/", "value": { "errorCode": "notification.smartphone.failed", "message": "Could not notify smartphone." }, "status": 424 } Scenario 5 - Long running live message scenario For this scenario the device is going to ask for an information which it needs eventually. Let’s say the device asks for the endpoint where it should download the new firmware from. It’s not required that this response arrives within a given time. It’s just required to eventually arrive at the device and after it was received the device can signal the user, that it is ready to download the firmware. The headers of the live message should have the following values: response-required=true requested-acks=["live-response"] Example Ditto Protocol message: { "topic": "org.eclipse.ditto/my-thing/things/live/messages/firmware", "headers": { "response-required": true, "requested-acks": ["live-response"], "content-type": "text/plain", "timeout": "5s" }, "path": "/outbox/messages/firmware", "value": "firmware.url.query" } By requesting the acknowledgement live-response the connectivity service will wait until the response for the live message arrived for 5s before acknowledging the incoming message at the broker and will request a redelivery if the response did not arrive within this timeout. This will repeat until either the broker discards the message or the response arrives in the specified timeout. That way it is guaranteed that the device will eventually receive the response. Scenario 6 - Asking for required information scenario For this scenario the device is going to ask for an information which it needs right now to proceed with its current task. Let’s say the device asks if it should allow a car with a license plate it detected to drive on the property by opening the barrier. It could be possible to ask for that information, so the barrier opens automatically, but providing a fallback mechanism like entering a code directly at the device if this response does not arrive within time. The headers of the live message should have the following values: response-required=true requested-acks=[] Example Ditto Protocol message: { "topic": "org.eclipse.ditto/my-thing/things/live/messages/car-enter", "headers": { "response-required": true, "requested-acks": [], "content-type": "text/plain", "timeout": "5s" }, "path": "/outbox/messages/car-enter", "value": "FN IB 1337" } By requesting explicitly not requesting any acknowledgement but still requiring a response, the connectivity service will immediately acknowledge the incoming message at the broker. The device will then either receive the response within the specified timeout or never. So the device can provide its alternative options to open the barrier after 5 seconds. We embrace your feedback I hope I could demonstrate the power of the new acknowledgement feature properly and could make it clear how it can be used. Maybe you did recognize some of your use cases in the given examples or maybe you have another use case which can or cannot be solved by this feature. We would love to get your feedback. – The Eclipse Ditto team [Less]
Posted about 5 years ago
E2E acknowledgement using Eclipse Ditto By adding the new acknowledgements feature to Ditto, it is now possible to provide an end to end QoS (quality of service) with level 1. Previously the connectivity service of Ditto did accept all incoming ... [More] messages immediately as soon as it received the message. This behaviour can now be controlled by a Ditto header called requested-acks. In this blog post I will provide a few examples for how to use this new feature in the following scenarios: Device publishes a change of its state and doesn’t care about whether the event regarding this change will be received by any subscriber or not. This is the fire and forget scenario. Device publishes a change of its state and wants to be sure it is persisted in Ditto. This is the processed in Ditto scenario. Device publishes a change of its state and wants to be sure an application connected to Eclipse Ditto will receive the event regarding this change of the state. This is the notification scenario. Device publishes a change of its state and wants to be notified when a subscriber was not able to receive the event regarding this change. This is the tracked notification scenario. Device sends a live message and wants to be sure that it will eventually receive a response. This is the long running live message scenario. Device sends a live message and wants to either receive the response within a given timeout or never. This is the asking for required information scenario. Scenarios The following scenarios all share the same context: a device sends data/messages via a device connectivity layer (e.g. Eclipse Hono or an MQTT broker) to Ditto Ditto’s connectivity service consumes the Ditto Protocol message forwards the message into the Ditto cluster to be processed is responsible for technically acknowledging/settling the consumed message at the device connectivity layer / broker the strategy of when this is done and with which outcome is handled by the Ditto headers mentioned in the scenarios Although all scenarios are based on the device sending something (e.g. telemetry data or a message), the E2E acknowledgement can also be used the other way around when e.g. a backend application sends something to a device. Scenario 1 - Fire and Forget This is the simplest scenario of all, since the change can be published in a fire and forget semantics. In this scenario the device will send the modification command containing the headers: response-required=false requested-acks=[] Example Ditto Protocol message: { "topic": "org.eclipse.ditto/my-thing/things/twin/commands/modify", "headers": { "response-required": false, "requested-acks": [] }, "path": "/features/lightSwitch/properties/status", "value": "on" } For this case the connectivity service will immediately acknowledge the incoming message at the messaging system and then continues to process the command. It doesn’t matter if the command could be processed successfully or if any subscriber received an event for this change. Scenario 2 - Processed in Ditto For this scenario the device wants to be sure its change will be properly persisted in Ditto. The command needs to define the following headers: response-required=false requested-acks=["twin-persisted"] Example Ditto Protocol message: { "topic": "org.eclipse.ditto/my-thing/things/twin/commands/modify", "headers": { "response-required": false, "requested-acks": ["twin-persisted"] }, "path": "/features/lightSwitch/properties/status", "value": "on" } For this case the connectivity service will wait until the modification will be properly persisted in Ditto before acknowledging the incoming message at the messaging system. If the device published this command for example via an AMQP broker (with a QoS 1 “at least once” semantic), this will cause the broker to redeliver the command to Ditto if the acknowledgment fails. Please be aware that a redelivery will only be requested for the following error status codes: 408 (Request timed out) 424 (Dependency Failure) All kinds of 5xx status codes In this scenario it does matter if the command could be processed successfully, but it’s still not relevant if any subscriber received an event for this change. Scenario 3 - Notification scenario For this scenario the device wants to be sure another system will be notified about the change of its state. This could be for example an alarming system which wants to be sure a backend application receives the information that the alarm was triggered. A prerequisite for this is that any kind of connection exists that publishes the event to the backend application and declares a user defined acknowledgement label. This can be a WebSocket session or any kind of Ditto Connection types which can be found here. For this example we expect the event to be forwarded by an HTTP connection which declared the following acknowledgement label as issued acknowledgement of the target: d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed. The UUID prefix in this case is the ID of the HTTP connection and thebackend-process part is a custom label, defined by the user. The command needs to define the following headers: response-required=false requested-acks=["d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed"] timeout=30s (optional. Default is 10s.) Example Ditto Protocol message: { "topic": "org.eclipse.ditto/my-thing/things/twin/commands/modify", "headers": { "response-required": false, "requested-acks": ["d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed"], "timeout": "30s" }, "path": "/features/alarm/properties/status", "value": "on" } For this case the connectivity service will wait until the HTTP request, which forwards the event regarding the thing change, will be finished before acknowledging the incoming message at the messaging system. The status code of the HTTP response will in this case determine if the message will be acknowledged successfully or not and if a redelivery will be requested or not. All kinds of 2xx status codes will lead to a successful acknowledgement at the messaging system. All other status codes will lead to a failed acknowledgement at the messaging system and for the following status codes a redelivery will be requested: 408 (Request timed out) 424 (Dependency Failure) All kinds of 5xx status codes In this scenario it is ensured a specified subscriber will receive an event for this change. Scenario 4 - Tracked notification scenario For this scenario the device wants to know when a system could not be notified about the change of its state. This could be for example an alarming system which wants to be sure a backend application receives the information, or if not: tries to send an SMS as notification. This scenario is mostly like scenario 3, but needs to set the response-required header to true and it’s required to configure the reply-target of the source to also expect “nack” responses. Example Ditto Protocol message: { "topic": "org.eclipse.ditto/my-thing/things/twin/commands/modify", "headers": { "response-required": true, "requested-acks": ["d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed"] }, "path": "/features/alarm/properties/status", "value": "on" } In this case the device will receive an acknowledgement response containing the status code and payload of the response of the backend application. Based on this the device can decide how to handle the situation. It is suggested to publish the modification command with QoS 0 (“at most once” semantics) in this case because the device handles the result of the E2E acknowledgement. With QoS 1 (“at least once” semantics) brokers would usually redeliver the message to Ditto. If the HTTP endpoint of the backend application responds with the following response: headers: "content-type": "application/json" body: { "errorCode": "notification.smartphone.failed", "message": "Could not notify smartphone." } status code: 424 The response received at the device would look like this: { "topic": "org.eclipse.ditto/my-thing/things/twin/acks/d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed", "headers": { "response-required": false, "requested-acks": ["d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed"], "timeout": "30s", "content-type": "application/json" }, "path": "/", "value": { "errorCode": "notification.smartphone.failed", "message": "Could not notify smartphone." }, "status": 424 } Scenario 5 - Long running live message scenario For this scenario the device is going to ask for an information which it needs eventually. Let’s say the device asks for the endpoint where it should download the new firmware from. It’s not required that this response arrives within a given time. It’s just required to eventually arrive at the device and after it was received the device can signal the user, that it is ready to download the firmware. The headers of the live message should have the following values: response-required=true requested-acks=["live-response"] Example Ditto Protocol message: { "topic": "org.eclipse.ditto/my-thing/things/live/messages/firmware", "headers": { "response-required": true, "requested-acks": ["live-response"], "content-type": "text/plain", "timeout": "5s" }, "path": "/outbox/messages/firmware", "value": "firmware.url.query" } By requesting the acknowledgement live-response the connectivity service will wait until the response for the live message arrived for 5s before acknowledging the incoming message at the broker and will request a redelivery if the response did not arrive within this timeout. This will repeat until either the broker discards the message or the response arrives in the specified timeout. That way it is guaranteed that the device will eventually receive the response. Scenario 6 - Asking for required information scenario For this scenario the device is going to ask for an information which it needs right now to proceed with its current task. Let’s say the device asks if it should allow a car with a license plate it detected to drive on the property by opening the barrier. It could be possible to ask for that information, so the barrier opens automatically, but providing a fallback mechanism like entering a code directly at the device if this response does not arrive within time. The headers of the live message should have the following values: response-required=true requested-acks=[] Example Ditto Protocol message: { "topic": "org.eclipse.ditto/my-thing/things/live/messages/car-enter", "headers": { "response-required": true, "requested-acks": [], "content-type": "text/plain", "timeout": "5s" }, "path": "/outbox/messages/car-enter", "value": "FN IB 1337" } By requesting explicitly not requesting any acknowledgement but still requiring a response, the connectivity service will immediately acknowledge the incoming message at the broker. The device will then either receive the response within the specified timeout or never. So the device can provide its alternative options to open the barrier after 5 seconds. We embrace your feedback I hope I could demonstrate the power of the new acknowledgement feature properly and could make it clear how it can be used. Maybe you did recognize some of your use cases in the given examples or maybe you have another use case which can or cannot be solved by this feature. We would love to get your feedback. – The Eclipse Ditto team [Less]
Posted about 5 years ago
E2E acknowledgement using Eclipse Ditto By adding the new acknowledgements feature to Ditto, it is now possible to provide an end to end QoS (quality of service) with level 1. Previously the connectivity service of Ditto did accept all incoming ... [More] messages immediately as soon as it received the message. This behaviour can now be controlled by a Ditto header called requested-acks. In this blog post I will provide a few examples for how to use this new feature in the following scenarios: Device publishes a change of its state and doesn’t care about whether the event regarding this change will be received by any subscriber or not. This is the fire and forget scenario. Device publishes a change of its state and wants to be sure it is persisted in Ditto. This is the processed in Ditto scenario. Device publishes a change of its state and wants to be sure an application connected to Eclipse Ditto will receive the event regarding this change of the state. This is the notification scenario. Device publishes a change of its state and wants to be notified when a subscriber was not able to receive the event regarding this change. This is the tracked notification scenario. Device sends a live message and wants to be sure that it will eventually receive a response. This is the long running live message scenario. Device sends a live message and wants to either receive the response within a given timeout or never. This is the asking for required information scenario. Scenarios The following scenarios all share the same context: a device sends data/messages via a device connectivity layer (e.g. Eclipse Hono or an MQTT broker) to Ditto Ditto’s connectivity service consumes the Ditto Protocol message forwards the message into the Ditto cluster to be processed is responsible for technically acknowledging/settling the consumed message at the device connectivity layer / broker the strategy of when this is done and with which outcome is handled by the Ditto headers mentioned in the scenarios Although all scenarios are based on the device sending something (e.g. telemetry data or a message), the E2E acknowledgement can also be used the other way around when e.g. a backend application sends something to a device. Scenario 1 - Fire and Forget This is the simplest scenario of all, since the change can be published in a fire and forget semantics. In this scenario the device will send the modification command containing the headers: response-required=false requested-acks=[] Example Ditto Protocol message: { "topic": "org.eclipse.ditto/my-thing/things/twin/commands/modify", "headers": { "response-required": false, "requested-acks": [] }, "path": "/features/lightSwitch/properties/status", "value": "on" } For this case the connectivity service will immediately acknowledge the incoming message at the messaging system and then continues to process the command. It doesn’t matter if the command could be processed successfully or if any subscriber received an event for this change. Scenario 2 - Processed in Ditto For this scenario the device wants to be sure its change will be properly persisted in Ditto. The command needs to define the following headers: response-required=false requested-acks=["twin-persisted"] Example Ditto Protocol message: { "topic": "org.eclipse.ditto/my-thing/things/twin/commands/modify", "headers": { "response-required": false, "requested-acks": ["twin-persisted"] }, "path": "/features/lightSwitch/properties/status", "value": "on" } For this case the connectivity service will wait until the modification will be properly persisted in Ditto before acknowledging the incoming message at the messaging system. If the device published this command for example via an AMQP broker (with a QoS 1 “at least once” semantic), this will cause the broker to redeliver the command to Ditto if the acknowledgment fails. Please be aware that a redelivery will only be requested for the following error status codes: 408 (Request timed out) 424 (Dependency Failure) All kinds of 5xx status codes In this scenario it does matter if the command could be processed successfully, but it’s still not relevant if any subscriber received an event for this change. Scenario 3 - Notification scenario For this scenario the device wants to be sure another system will be notified about the change of its state. This could be for example an alarming system which wants to be sure a backend application receives the information that the alarm was triggered. A prerequisite for this is that any kind of connection exists that publishes the event to the backend application and declares a user defined acknowledgement label. This can be a WebSocket session or any kind of Ditto Connection types which can be found here. For this example we expect the event to be forwarded by an HTTP connection which declared the following acknowledgement label as issued acknowledgement of the target: d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed. The UUID prefix in this case is the ID of the HTTP connection and thebackend-process part is a custom label, defined by the user. The command needs to define the following headers: response-required=false requested-acks=["d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed"] timeout=30s (optional. Default is 10s.) Example Ditto Protocol message: { "topic": "org.eclipse.ditto/my-thing/things/twin/commands/modify", "headers": { "response-required": false, "requested-acks": ["d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed"], "timeout": "30s" }, "path": "/features/alarm/properties/status", "value": "on" } For this case the connectivity service will wait until the HTTP request, which forwards the event regarding the thing change, will be finished before acknowledging the incoming message at the messaging system. The status code of the HTTP response will in this case determine if the message will be acknowledged successfully or not and if a redelivery will be requested or not. All kinds of 2xx status codes will lead to a successful acknowledgement at the messaging system. All other status codes will lead to a failed acknowledgement at the messaging system and for the following status codes a redelivery will be requested: 408 (Request timed out) 424 (Dependency Failure) All kinds of 5xx status codes In this scenario it is ensured a specified subscriber will receive an event for this change. Scenario 4 - Tracked notification scenario For this scenario the device wants to know when a system could not be notified about the change of its state. This could be for example an alarming system which wants to be sure a backend application receives the information, or if not: tries to send an SMS as notification. This scenario is mostly like scenario 3, but needs to set the response-required header to true and it’s required to configure the reply-target of the source to also expect “nack” responses. Example Ditto Protocol message: { "topic": "org.eclipse.ditto/my-thing/things/twin/commands/modify", "headers": { "response-required": true, "requested-acks": ["d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed"] }, "path": "/features/alarm/properties/status", "value": "on" } In this case the device will receive an acknowledgement response containing the status code and payload of the response of the backend application. Based on this the device can decide how to handle the situation. It is suggested to publish the modification command with QoS 0 (“at most once” semantics) in this case because the device handles the result of the E2E acknowledgement. With QoS 1 (“at least once” semantics) brokers would usually redeliver the message to Ditto. If the HTTP endpoint of the backend application responds with the following response: headers: "content-type": "application/json" body: { "errorCode": "notification.smartphone.failed", "message": "Could not notify smartphone." } status code: 424 The response received at the device would look like this: { "topic": "org.eclipse.ditto/my-thing/things/twin/acks/d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed", "headers": { "response-required": false, "requested-acks": ["d45d4522-142e-4057-ae87-8969343a3ddc:backend-processed"], "timeout": "30s", "content-type": "application/json" }, "path": "/", "value": { "errorCode": "notification.smartphone.failed", "message": "Could not notify smartphone." }, "status": 424 } Scenario 5 - Long running live message scenario For this scenario the device is going to ask for an information which it needs eventually. Let’s say the device asks for the endpoint where it should download the new firmware from. It’s not required that this response arrives within a given time. It’s just required to eventually arrive at the device and after it was received the device can signal the user, that it is ready to download the firmware. The headers of the live message should have the following values: response-required=true requested-acks=["live-response"] Example Ditto Protocol message: { "topic": "org.eclipse.ditto/my-thing/things/live/messages/firmware", "headers": { "response-required": true, "requested-acks": ["live-response"], "content-type": "text/plain", "timeout": "5s" }, "path": "/outbox/messages/firmware", "value": "firmware.url.query" } By requesting the acknowledgement live-response the connectivity service will wait until the response for the live message arrived for 5s before acknowledging the incoming message at the broker and will request a redelivery if the response did not arrive within this timeout. This will repeat until either the broker discards the message or the response arrives in the specified timeout. That way it is guaranteed that the device will eventually receive the response. Scenario 6 - Asking for required information scenario For this scenario the device is going to ask for an information which it needs right now to proceed with its current task. Let’s say the device asks if it should allow a car with a license plate it detected to drive on the property by opening the barrier. It could be possible to ask for that information, so the barrier opens automatically, but providing a fallback mechanism like entering a code directly at the device if this response does not arrive within time. The headers of the live message should have the following values: response-required=true requested-acks=[] Example Ditto Protocol message: { "topic": "org.eclipse.ditto/my-thing/things/live/messages/car-enter", "headers": { "response-required": true, "requested-acks": [], "content-type": "text/plain", "timeout": "5s" }, "path": "/outbox/messages/car-enter", "value": "FN IB 1337" } By requesting explicitly not requesting any acknowledgement but still requiring a response, the connectivity service will immediately acknowledge the incoming message at the broker. The device will then either receive the response within the specified timeout or never. So the device can provide its alternative options to open the barrier after 5 seconds. We embrace your feedback I hope I could demonstrate the power of the new acknowledgement feature properly and could make it clear how it can be used. Maybe you did recognize some of your use cases in the given examples or maybe you have another use case which can or cannot be solved by this feature. We would love to get your feedback. – The Eclipse Ditto team [Less]
Posted about 5 years ago
Before Ditto Java Client 1.3.0, a client object connects to a configured Ditto back-end during its creation. // create a client object and block until it connects to the Ditto back-end. final DittoClient client = ... [More] DittoClients.newInstance(messagingProvider); There are several problems with the approach. The calling thread blocks waiting for IO, namely the authentication process and establishment of a websocket. If the client is configured to reconnect, then an incorrect end-ponit configuration makes the factory method block forever. If the client is not configured to reconnect, then the factory method will throw an exception. But it is not possible to give the client reference to the exception handler, since the client creation did not complete. Consequently the exception handler has no simple way to free all resources allocated for the client. 1.3.0 addresses these problems by introducing an asynchronous client creation interface. public final class DittoClients { public static DisconnectedDittoClient newDisconnectedInstance(MessagingProvider mp); } public interface DisconnectedDittoClient { CompletionStage<DittoClient> connect(); void destroy(); } The method DittoClients.newDisconnectedInstance(MessagingProvider) creates a DisconnectedDittoClient object. The DisconnectedDittoClient has references to all resources allocated for the client and can free them via the destroy() method. The DisconnectedDittoClient object offers no method to interact with the Ditto API. By calling connect(), one obtains a future that yields a familiar DittoClient object upon completion. One might use the asynchronous client creation interface thus: final DisconnectedDittoClient disconnectedClient = DittoClients.newDisconnectedInstance(messagingProvider); disconnectedClient.connect() .thenAccept(this::startUsingDittoClient) .exceptionally(exception -> { this.handleConnectionFailure(exception); disconnectedClient.destroy(); return null; }); The asynchronous client creation interface has the following advantages. The calling thread does not block. Even if configured to reconnect, the user can receive connection errors via the connection error handler in MessagingConfiguration and shut down the client at will. When initial reconnection is disabled, the method DisconnectedDittoClient.connect() returns a failed future on connection error. It is possible to reference the DittoDisconnectedClient object in the future’s error handler, where the client can be destroyed. – The Eclipse Ditto team [Less]