Skip to main content

hiiretail-socketio-service

Socket IO Overview

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.

RolePermissionsDescription
sio.websocket-clientsio.websocket.connect, sio.websocket.read, sio.websocket.ackCreate a socket connection and consume messages.

Usage

The service has two use cases

  1. Client on edge that needs to consume async messages, typically events
  2. 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

  1. With OCMS token
  2. With IAM user token
  3. 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 or buid
  • workstation_id or wid

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 include correlationId 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.