Extend S3I Directory Model to allow describing Events
After the introduction of Events to the S3I-B protocol we now need a way to describe them in the directory.
This proposal includes the addition of a new type, S3I::Event
and changing the way S3I::Endpoint
s are assigned.
To subscribe to an Event via AMQP, for example, you need the address of the broker instance (rabbitmq.s3i.vswf.dev:5672
), the virtual host (vhost, e.g. s3i
), the name of the exchange (e.g. eventExchange
) and the routing key (e.g. s3i:someId.eventName
).
Events using MQTT would require the broker instance and a topic.
It is possible to encode this information in a single url.
We currently omit a lot of this information. This works, because the SDKs have this information hardcoded. I believe we should explicitly state this everytime.
// Current (Omits Broker address, virtual host and exchange)
{
"uri": "s3ib://someid"
}
// Proposed: State all information explicitly
{
"uri": "s3ib://rabbitmq.s3i.vswf.dev:5672/s3i/eventExchange/s3i:1234.newStrainGaugeMeasurement",
}
Change
S3I::Object/Value/Service
: The current data model has an aggregation relationship between S3I::Object/Value/Service
and S3I::Endpoint
.
To my knowledge json does not offer a way to realize this relationship without further fields.
This problem has not occured in practice, because we never defined endpoints for individual S3I::Value
or S3I::Service
.
A single default endpoint was sufficient, because all messages were directly routed to the things queue.
I feel it would be much simpler to instead have a composition relationship between S3I::Object/Value/Service
and S3I::Endpoint
.
// Current
{
?
}
// Proposed
{
"endpoints": [
]
}
Consequently, I propose renaming the property S3I::Thing::allEndpoints
to S3I::Thing::endpoints
, since it doesn't include all endpoints any more.
Likewise, there is no clear way of realizing the S3I::Thing::defaultEndpoint
relationship. I propose removing this, and treating the endpoints under S3I::Thing::endpoints
as default.
Addition
With these changes we can now introduce the new type S3I::Event
. Like S3I::Object/Value/Service
it has endpoints.
I also propose the fields name
, description
, dataformat
, schemaType
and schema
.
I believe dataformat
helps if someone decides to format his/her event body in something other than JSON.
As a guideline, we should assume as little as possible and be explicit about as much as possible.
The proposed schemaType
and schema
fields are in this spirit.
In practice, a clear description of the contents of events, or any message actually, would have been incredibly helpful.
Too many times did some message exchange not work because the case of some key wasn't matching (e.g. min
vs. Min
).
The example below contains a JSON Schema, which I find suitable, but I don't think this should be constrained.
Therefore the schema
field can be any object in my mind.
I'm looking forward to comments on this issue.
{
"endpoints": [
{
"uri": "s3ib://rabbitmq.s3i.vswf.dev:5672/s3i/eventExchange/s3i:1234.newStrainGaugeMeasurement",
}
],
"name": "newStrainGaugeMeasurement",
"description": "This event is emitted if ...",
"dataformat": "json",
"schemaType": "JSONSchema",
"schema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"title": "newStrainGaugeMeasurement",
"description": "JSON Schema for content field of this EventMessage",
"properties": {
"stretch": { "type": "number" },
"force": { "type": "number" },
"displacement": {
"type": "array",
"items": { "type": "number" }
}
}
}
}
I currently don't have access to EA, so I'm posting a reduced UML Graphic of the proposed data model via mermaid. I will replace this as soon as possible.
classDiagram
Root *-- Thing : things
Root : apiVersion string
Thing *-- Object : thingStructure 0..1
Object *-- Endpoint : endpoints
Object *-- Value : values
Object *-- Service : services
Object *-- Event : events
Value *-- Endpoint : endpoints
Service *-- Endpoint : endpoints
Event *-- Endpoint : endpoints
Thing *-- Endpoint : endpoints
Endpoint : uri string
Event : name string
Event : description string
Event : dataformat string
Event : schemaType string
Event : schema object
Complete example
{
"name": "Real Cantilever",
"thingId": "s3i:9e3a89d9-8c5d-41cf-90fc-9aaf7325aca4",
"policyId": "s3i:9e3a89d9-8c5d-41cf-90fc-9aaf7325aca4",
"defaultEndpoint": "s3ib://s3i:9e3a89d9-8c5d-41cf-90fc-9aaf7325aca4",
"type": "component",
"thingStructure": {
"class": "Cantilever",
"id": "1234",
"services" : [
{
"serviceType": "setConfiguration",
"parameterTypes": {
"length": "number",
"width": "number",
"height": "number",
"thickness": "number",
"geometryType":"string",
"materialType":"string",
"sensorPosition": "number",
"calibrationOffset": "number",
"calibrationScaling": "number"
},
"resultTypes": {
"ok": "bool"
},
}
],
"events": [
{
"endpoints": [
{
"uri": "s3ib://rabbitmq.s3i.vswf.dev:5672/s3i/eventExchange/s3i:1234.newStrainGaugeMeasurement"
}
],
"name": "newStrainGaugeMeasurement",
"description": "This event is emitted if ...",
"dataformat": "json",
"schemaType": "JSONSchema",
"schema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"title": "newStrainGaugeMeasurement",
"description": "JSON Schema for content field of this EventMessage",
"properties": {
"stretch": { "type": "number" },
"force": { "type": "number" },
"displacement": {
"type": "array",
"items": { "type": "number" }
}
}
}
}
]
}
}
The proposed change from S3I::Thing::allEndpoints
to S3I::Thing::endpoints
and restructuring of S3I::Endpoint
are breaking changes.
I suggest collecting these, along with other pending changes and work towards a new api version.
We haven't increased the api version with the position paper 2.0
, so I suggest directly increasing to 3.0
alongside the new documentation.