Event Stream#
Clients receive information about changes to their data by subscribing to an event stream. The stream is specific to the person and can contain events from multiple services the person is using.
The purpose of the stream is not to deliver the changes itself but rather notify the subscriber of changes. Events are meant to "wake up" the client. Clients must use application-specific APIs to fetch the actual changes.
As a result of this, subscription to the event stream is authenticated using a weak uidToken
.
Stream details#
The bidirectional stream is implemented following WebSockets. It is to be consumed by the WebSockets interface. The server supports WebSocket version 13 and sub-protocol skalioid
. Connections can be opened without authentication. Connections may be terminated by the server at regular intervals, after which clients can reestablish them.
Once the connection is opened, the client should interact with the endpoint to subscribe to the event stream in order to receive events. Failing to do so will leave the connection dormant. Subscribing to a stream requires authentication. Once a subscription is established, the event stream will publish events over it. A client may choose to unsubscribe again, which requires authentication again.
Messages sent over the socket are text messages containing JSON payload, prefixed by a keyword. Examples:
EventsRequest{"id": "1f21hjani076gr130c4jg0emt0h8mjgb", "token": "eyJ0eXAiOiJKV1Qi...LQHOB6ZYNdQlSiaI", "action": "subscribe", "productId": "com.skalio.id"}
EventsResponse{"id" : "1f21hjani076gr130c4jg0emt0h8mjgb", "status" : 401, "message" : "Unauthorized"}
SignalingEvent{"type": "PROFILE_ACTIVITY", "timestamp", "2019-12-02T14:02:33.694Z", "data": "qa7g-r1.30c4jg0emt"}
Payload EventsRequest#
Clients can send an EventsRequest to manage event stream subscriptions. The JSON payload must be prefixed with the String EventsRequest
. Fields:
id
: String, required. Request ID set by the client to an arbitrary value. It will be returned in an EventsResponse to allow matching.token
: String, required. Uid token, used for authentication.action
: String, required. One ofsubscribe
,unsubscribe
.productId
: String, required. Identifies the product that the client wants to subscribe to.
Payload EventsResponse#
The server endpoint will respond to a EventsRequest by returning an EventsResponse JSON object, prefixed with the String EventsResponse
. Fields:
id
: String, optional. Contains the value ofid
from the matching EventsRequest, if one exists.status
: Number, required. Indicates the success of the operation. Uses HTTP status codes.message
: String, optional. May include informational text about the result.
Payload SignalingEvent#
A SignalingEvent is specific to the WebSocket that receives it. It holds information about the status of the individual connection.
The stream delivers its message as a JSON-encoded payload, prefixed with the String SignalingEvent
. It has no sequence or ID, instead it has a timestamp. Depending on the type, it may also contain different metadata. Events are not cached and past events cannot be replayed. Fields:
uid
: String, required. Contains the uid of the intended recipient.timestamp
: String, required. ISO-8601 encoded timestamp of the event.type
: String, required. See below.data
: String, optional. Use depends on value oftype
; see below.
Type | Description | Data-field contents |
---|---|---|
PROFILE_ACTIVITY | Data has changed in the profile of a person. | uid of person |
PROFILE_AVATAR_UPDATED | The avatar of a person has been updated or removed. | uid of person |
PROFILE_VERIFIED | The primary email address of a person has been verified. | uid of person |
SPACE_ACTIVITY | Data has changed in a subscribed space. | uid of subscribed space |
SPACE_PROGRESS_ACTIVITY | A long-running operation on an object is running. | See Space Progress Activity |
SPACE_UPLOAD_ABORTED | An upload was interrupted unexpectedly. See Personal Events. | See Space Upload Aborted |
SPACE_CAPACITY_UPDATED | The capacity limits or usage of Novospace has changed. | ICapacity object |
FEEDBACK_INVITATION | The person is invited to submit feedback regarding the product. | null |
FEEDBACK_RECEIVED | Feedback for a product has been received. | null |
SUBSCRIPTION_UPDATED | A subscription has been created or has changed. | See ISubscriptionUpdate |
PURCHASE_PENDING | A checkout session has been created. The person is editing their organization's subscription. | uid of the organization |
ORGANIZATION_PROFILE_UPDATED | The organization profile has been created or updated. | uid of the organization |
ORGANIZATION_AVATAR_UPDATED | The organization profile has been created, updated or removed. | uid of the organization |
PRIVILEGES_UPDATED | The organization membership and/or assigned roles of the person have been changed. | uid of the organization |
INVITATION_ACTIVITY | The list of invitations of a person has changed. | null |
Authentication#
The subscription to the stream must be authenticated with a valid uid token, granting read-privileges to the stream. The same uid token can be used establishing multiple feeds, or each feed can use individual uid tokens.
The server will sporadically disconnect clients before token validity runs out. In such a case, upon resubscription, the client must then present a new, valid uid token.
The uid token implies very little authorization and requires only limited protection. It is acceptable to use the uid token as part of the query string in URLs, where it is more likely to be discovered by or (inadvertently) exposed to other persons.
As a result, the event stream cannot be guaranteed to be entirely private.
Architecture#
When a person successfully subscribes to an event stream, he registers an event sink. This sink is registered in the event sink store. The sink is associated with the person, to allow addressing messages to the correct sinks.
The event broadcast bridge subscribes to a topic on the message broker and directs incoming events to the event sink store. Here each event is sent to the correct sink.
Other applications can send events to persons by publishing them on the message broker. Since the event stream only delivers notifications of changes, acting as a wake-up-call, the application should provide a resource where the person can retrieve the actual change details.
It is important to understand that this architecture offers dealing with change-events in an asynchronous way. The person is not required to act upon events immediately. In fact, it could be beneficial to delay and instead fetch multiple change details.