hiiretail-socketio-service
This is a microservice that can stream messages from Pub/Sub to edge workloads over a websocket. The stream is implemented with SocketIO. Clients must use a SocketIO client to consume events.
Features
- Unidirectional websocket event streaming from Pub/Sub to edge
- Broadcast or route messages to specific recipients
- Support for OCMS and Hii Retail IAM Auth
Bidirectional messaging is currently not supported. Generally data is pushed to services via REST APIs of the respective services.
Message routing
Messages can be delivered to edge applications and target
- The tenant
- A business unit
- A workstation in a business unit
- A session at a workstation in a business unit
Messages can also target users identified by the user profile id
- A user
- A user in a business unit
There is also a way to specify custom routing
Roles and permissions
This service defines the follow built-in roles and permissions.
Role | Permissions | Description |
---|---|---|
sio.websocket-client | sio.websocket.connect , sio.websocket.read , sio.websocket.ack | Create a socket connection and consume messages. |
Usage
The service has two use cases
- Client on edge that needs to consume async messages, typically events
- Services in GCP that needs to publish events to edge
Consumer - SocketIO client
The consumer must use a SocketIO client that supports the v4 protocol. The service only supports websockets and any attempts to fall back to long-polling will fail.
Note: even though socketio works over websocket, direct connection via websocket is not supported.
Examples will use the Javascript client.
import { io } from 'socket.io-client';
Connect
Edge workloads can connect to the stream in two ways
- With OCMS token
- With IAM user token
- With OCMS and IAM tokens
The authorization methods dictates what types of messages the client will receive.
Connect with OCMS
If only OCMS is used, this typically means the workload is unattended or not operated by a human for the time being.
This type of client can receive messages directed towards the tenant, the business unit and the workstation. The following OCMS claims are supported:
business_unit_id
orbuid
workstation_id
orwid
The OCMS template should have the role sio.websocket-client
.
const socket = io('https://socketio.retailsvc.com', {
transport: ['websocket'],
auth: {
token: 'OCMS token <no bearer prefix>',
},
});
This type of connection will join rooms:
tenants/{tenantId}
tenants/{tenantId}/connections/{connectionId}
tenants/{tenantId}/business-units/{businessUnitId}
tenants/{tenantId}/business-units/{businessUnitId}/workstations/{workstationId}
Connect with IAM token
If only an IAM token is used, this typically means the workload isn't associated with a specific business unit.
This type of client can receive messages directed towards the tenant or the user.
The user must have the role sio.websocket-client
.
const socket = io('wss://socketio.retailsvc.com', {
transport: ['websocket'],
auth: {
token: 'IAM token',
},
});
This type of connection will join rooms:
tenants/{tenantId}
tenants/{tenantId}/connections/{connectionId}
tenants/{tenantId}/users/{userId}
Connect with OCMS and IAM
With both an OCMS and IAM token, we can target active users working in specific applications, in specific stores.
This type of client will receive messages for the tenant, business-unit, workstation, user or the specific user session.
The OCMS template should have the role sio.websocket-client
. The user is not required to have any
specific roles or permissions.
const socket = io('wss://socketio.retailsvc.com', {
transport: ['websocket'],
auth: {
token: 'OCMS token',
},
query: {
userToken: 'IAM token',
sessionId: '73edd50c-4b5b-45a0-a236-e72809698d9d',
topics: ['che.public.event.session-changed.v1'],
},
});
This type of connection will join rooms:
topics/{topicId}
topics/{topicId}/tenants/{tenantId}
topics/{topicId}/tenants/{tenantId}/connections/{connectionId}
topics/{topicId}/tenants/{tenantId}/users/{userId}
topics/{topicId}/tenants/{tenantId}/business-units/{businessUnitId}
topics/{topicId}/tenants/{tenantId}/business-units/{businessUnitId}/workstations/{workstationId}
topics/{topicId}/tenants/{tenantId}/business-units/{businessUnitId}/users/{userId}
Advanced routing in business unit
additionalBusinessUnitRooms
The service supports additional rooms for business units. This can be used to target specific workstations, workstation types or anything else really withing a context of Business Unit.
const socket = io('wss://socketio.retailsvc.com', {
// ... other config
query: {
additionalBusinessUnitRooms: [
'workstations/001',
'workstations/002',
'workstation-types/scanngo',
],
},
});
In the example above consumer will join in addition to rooms described before to:
tenants/{tenantId}/business-units/{businessUnitId}/workstations/001
tenants/{tenantId}/business-units/{businessUnitId}/workstations/002
tenants/{tenantId}/business-units/{businessUnitId}/workstation-types/scanngo
Note: additionalBusinessUnitRooms are not limited to workstations, you can use any string as a room name. But it will be always appended to tenants/{tenantId}/business-units/{businessUnitId} Note: Additional Business Unit Rooms are supported only for OCMS and OCMS+IAM connections.
To connect to additional bu rooms, your OCMS template should have the role sio.bu-rooms-client
(that has sio.bu-rooms.join
permission)
Producer will need to specify an attribute Additional-Business-Unit-Rooms
with a comma-separated list of bu rooms.
Example:
Additional-Business-Unit-Rooms: 'workstations/001,workstation-types/scanngo'
This attribute will tell socketio to route message to tenants/{tenantId}/business-units/{businessUnitId}/workstation-types/scanngo
and tenants/{tenantId}/business-units/{businessUnitId}/workstations/001
rooms.
Note: Additional-Business-Unit-Rooms attribute supports an array of rooms, to send multiple values, join them with a comma.
This attributes only works with Business-Unit-Id
attribute.
Consume events
Once connected, clients can consume messages based on their Pub/Sub event name.
const topic = 'che.public.event.session-changed.v1';
socket.on(topic, (data, meta) => {
// Handle message...
// che.public.event.session-changed.v1 - original name of topic in pub/sub
// meta is a JS object, message metadata
// data is a JS object, from the Pub/Sub event payload
// if data is not a json object, it will be base64 encoded
});
data
- The message payload. If payload is valid JSON, client will receive JS Object. If not, client will receive base64 encoded string.meta
- The message metadata. Contains the following properties:publishTime
- The time the message was published, ISO format. Example -2021-05-04T12:00:00.000Z
.messageId
- The Pub/Sub message ID.tenantId
- The hiiretail tenant id.- meta will also include all attributes from original Pub/Sub message converted to Camel Case. Example: If
Correlation-Id
attribute is included in p/s message,meta
will includecorrelationId
property.
Note: socketio is a generic service, that means it will deliver any message that is sent to it. Each individual Hiiretail service should be able to provide what kind of topics they expose and the schema of the body and attributes
Topics list
The socketio service as such, does not own 'topics'. Topics are defined by the services that publish messages to the SocketIO service. Connect with the service owner to get a list of topics that are available for their service. Owner should also provide the schema of the message body and attributes.