The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in IETF BCP14 (RFC2119 & RFC8174)
Copyright (c) 2023 General Motors GTO LLC Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. SPDX-FileType: DOCUMENTATION SPDX-FileCopyrightText: 2023 General Motors GTO LLC SPDX-License-Identifier: Apache-2.0
Publisher & Subscribers Architecture pattern allows subscribers to subscribe to topics published by publisher that can be running on the same device and/or different devices who’s connection to each other could even be temporal.
Off the shelf broker and broker-less solutions, rely on specific Internet protocols that do not scale for automotive use cases nor do they support producers and consumers that talk different pub/sub protocols (ex. MQTT, DDS, SOME/IP, proprietary, etc…).
uSubscriptions purpose is to explain how the distributed publisher-subscriber architecture pattern can be implemented through a ubiquitous language and communication protocol across the distributed devices. We will define the interfaces, sequences, and state machines to be able to support the use cases mentioned above.
Note
|
uSubscription interface is declared in usubscription.proto and follows uProtocol Error Model for return codes. |
A topic describes what the calling applications (subscribers) wants to subscribe too. Topic are expressed in uProtocol URIs format. Topics used in uSubscription APIs have the additional requirements of:
-
MUST contain
UEntity
andUResource
information -
UE_VERSION
MUST contain theMAJOR
, MUST NOT contain theMINOR
orPATCH
Note
|
Only the MAJOR is used in topics to support backwards compatibility between minor version updates of uEs to avoid the need to re-subscribe to topics when the uE MAJOR was not updated. Subscribers MUST re-subscribe to topics when the uE MAJOR version has changed
|
Example: /body.access/1/door.front_left#Door
In the following section we will elaborate on the states that a subscription can transition in and out from based on the various APIs called by producers and consumers.
Note
|
SUBSCRIBE_PENDING and UNSUBSCRIBE_PENDING states only apply to remote topic subscriptions, more details shall be provided below.
|
State | Description | Entry | Do | Exit |
---|---|---|---|---|
|
Subscriber uE is not subscribed but the topic exists |
|
Subscribe() is called by a consumer |
|
|
Subscriber uE is subscribed to the topic |
Subscription request has been processed and accepted |
* Subscriber has called Unsubscribe() |
|
|
Subscription is pending acknowledgement from the remote SubscriptionService |
1st Subscriber uE has called Subscribe() to a remote topic |
Forwards the subscription request to the destination device’s SubscriptionService |
Received a response from the remote SubscriptionService |
|
Unsubscribe is pending processing by the producers remote uBus |
Last subscriber called Unsubscribe() |
|
The uSubscription service notifies observers when there is a change in a subscription states by publishing notification events to the topic /core.usubscription/3/subscriptions#Update
. Below are the specific nuances about the subscription change notification based on the observer type.
Subscribers are automatically registered to receive subscription change notifications for topics they have subscribed too through the Subscribe() API.
-
Subscribers MUST NOT call the
RegisterForNotifications(
) as they are not permitted to receive notifications for subscription changes by other subscribers -
Subscription change notification MUST be sent whenever the
SubscriptionState
changes for said subscriber (ex,SUBSCRIBE_PENDING
→SUBSCRIBED
)
-
MUST NOT be permitted to call
RegisterForNotifications()
for topics they do not produce, i.e. the uEntity sending the request is not equal to theUEntity
of the request message’sUUri
parameter. -
Subscription change notifications MUST be sent for changes to
SubscriptionState
for any subscriber that is subscribed to the topic
The uSubscription service also allows to indicate to subscribers how they shall consume published events by means of the EventDeliveryConfig
returned in the SubscriptionResponse
message. For example, if the subscriber has to consume from a different topic or from different messaging infrastructure, this message will store the corresponding delivery semantics.
Note
|
Delivery semantics (if any) are deployment specific and not covered in this specification |
In the following section, we will elaborate on the various subscription flows for local and remote topics. When a consumer subscribes to a remote topic, it is the responsibility of the (local) uSubscription service to relay the subscription request to the remote uSubscription service as can be seen in the sequence diagrams below.
Note
|
Throughout this section we will use the sample topic //Device1/uexample/1/resource#Event to illustrate the various sequences. The above-mentioned topic will be replaced with topic in the diagrams
|
Subscription flow will show how a subscriber can subscribe to the example topic when uApp is on the same device (local subscriptions) or remote device (remote subscriptions).
-
uSubscription MUST change the subscriber to itself (core.usubscription) when subscribing to remote topics, this allows the reverse flow (publication) to be properly multicasted to local subscribers by the local disaptcher (ex. uBus) when it queries the local uSubscription for a list of local subscribers
Subscribe (and unsubscribe) to remote topics are handled by RPC calls between uSubscription services running on the different devices. Given that devices are not always connected to each other, the onus is on uSubscription service to ensure that a command is received in time. Below are the common retry and timeout policies for USubscription service implementations to follow:
-
Remote requests MUST have a maximum timeout of 5 minutes
-
All timed-out remote commands MUST be retied indefinitely until the business logic behind it no longer requires the command to be sent. (ex. the subscriber cals
Unsubscribe()
) -
Remote commands MUST be retried upon device to device connectivity (link up) and MUST NOT be tried when there is no device connectivity (link down)