Pub/Sub Events
While some applications simply send messages to connected clients, other applications need to be notified about events as they occur inside Hotsock. The following events can be published in real-time to either SNS or EventBridge and subscribed to by your applications.
By default, events are not published. If you know nothing is listening, there's no reason to pay the SNS publishing costs or EventBridge publishing costs for those messages. You can enable one or both without affecting Hotsock performance and can disable event publishing at any time.
The Hotsock event bus and SNS topics must be considered read-only. They should only ever be used for subscribing and consuming events. Do not publish custom events or attempt to replay past events directly into the Hotsock pub/sub topic or event bus. Bad things will happen. Always use the public APIs for writing/publishing to Hotsock.
Event format
Published events use the same shape for both EventBridge and SNS, where the payload is JSON on the detail
object in EventBridge events and a JSON string in the Message
attribute for SNS messages. Both support filtering subscribed events based on content of this message body. SNS also includes source
, type
, dataType
, and the keys/values in metadata
as MessageAttributes
to give flexibility in your SNS filter policies.
{
"source": "hotsock.v1",
"type": "hotsock.connected",
"metadata": {},
"data": {
"id": "IDnAdd9kIAMCEsQ=",
"connectedAt": "2024-05-31T15:47:45.231141792Z",
"keepAlive": true,
"sourceIp": "155.186.123.137",
"uid": null,
"umd": null,
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:126.0) Gecko/20100101 Firefox/126.0"
},
"dataType": "connection"
}
source
This indicates where the event originated and is set to "hotsock.v1" for all events.
Events intended for consumption by your applications (the events listed below) set source
to "hotsock.v1".
Hotsock-internal events are published to a separate SNS topic. Nothing stops you from subscribing to Hotsock-internal events on that topic. Just know that they're not guaranteed to be API-stable across installation versions.
type
String
- This is the type of the event, indicating what action was taken that triggered the event. hotsock.connected
, hotsock.disconnected
, hotsock.subscribed
, etc.
metadata
Object
- Metadata is an attribute that contains additional information about the event, data that may or may not also be contained in data
. For example, any event that has anything to do with a channel has a channel
property set in metadata. See each event type below to know which metadata attributes are included, if any. All metadata items have String
keys and String
values.
data
Object
- Data is the event payload. Items in this object are detailed below in the listing of event types. All items have String
keys and varying value types.
dataType
String
- This attribute indicates the kind of object that will be found in the data
attribute. For example, connection
objects have a different shape than subscription
objects, so this hints at the expected object shape.
Compatibility
New event types may be added to the "hotsock.v1" source namespace in minor version updates (1.x). Configure SNS filter policies or EventBridge rules for specific events to avoid unexpectedly receiving new events.
Additionally, new attributes may be added to existing event metadata
and data
objects for existing types in minor version updates. Any reasonable JSON parser should have no trouble with this.
Enable/disable EventBridge or SNS events
- Sign into your AWS account as a principal with administrative permissions and open the CloudFormation console. Find the root Hotsock stack and click on it. There are many Hotsock stacks marked as "nested", you'll want to ignore those and find the root stack that is not marked as nested.
- In the upper-right, click the "Update" button. Conveniently, if you accidentally try and update a nested stack, it will suggest that you instead go to the root stack.
- On the "Prepare template" screen, choose "Use current template" option.
- On the "Specify stack details" screen, set
PublishEventsToEventBridgeParameter
toenabled
to enable EventBridge events. Set todisabled
to disable EventBridge events. SetPublishEventsToSNSParameter
toenabled
to enable SNS events. Set todisabled
to disable SNS events. - Scroll to the bottom and click "Next".
- Scroll to the bottom of the "Configure stack options" screen and click "Next".
- Scroll to the bottom of the "Review Hotsock" screen, check all the boxes in the "Capabilities and transforms" section and click "Submit".
The setting is applied immediately and messages begin publishing as soon as the stack update completes.
EventBridge
If enabled, all events are published to a Hotsock-specific event bus in your account. The Arn of the event bus is available in your installation's stack outputs.
{
"version": "0",
"id": "f1b73bbb-b1f9-acd7-3b4c-4cf40db7328e",
"detail-type": "connection",
"source": "hotsock.v1",
"account": "111111111111",
"time": "2023-07-14T14:05:05Z",
"region": "us-east-1",
"resources": [],
"detail": {
"source": "hotsock.v1",
"type": "hotsock.connected",
"metadata": {},
"data": {
"id": "IDnAdd9kIAMCEsQ=",
"connectedAt": "2024-05-31T15:47:45.231141792Z",
"keepAlive": true,
"sourceIp": "155.186.123.137",
"uid": null,
"umd": null,
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:126.0) Gecko/20100101 Firefox/126.0"
},
"dataType": "connection"
}
}
Configure an EventBridge rule
SNS
If enabled, all messages are published to a Hotsock-specific SNS topic in your account. The Arn of the topic is available in your installation's stack outputs.
The following is a sample SNS message for a newly established connection. Most of the attributes may just look like noise, but the Message
attribute contains the event, which is always published as stringified JSON. Additionally, some properties are duplicated into MessageAttributes
for common SNS filter policy needs.
{
"Type": "Notification",
"MessageId": "4360060f-c95a-58d5-8a7c-58dbecd688ed",
"TopicArn": "arn:aws:sns:us-east-1:111111111111:Hotsock-PubSub-EOLFPNQLL8CW-Topic-AZXpBXfkywWc",
"Message": "{\"source\":\"hotsock.v1\",\"type\":\"hotsock.connected\",\"metadata\":{},\"data\":{\"id\":\"YppzrdWfoAMCJBQ=\",\"umd\":null,\"connectedAt\":\"2024-05-31T19:21:47.747616027Z\",\"keepAlive\":true,\"uid\":null,\"userAgent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:126.0) Gecko/20100101 Firefox/126.0\",\"sourceIp\":\"155.186.123.137\"},\"dataType\":\"connection\"}",
"Timestamp": "2024-05-31T19:21:48.428Z",
"SignatureVersion": "1",
"Signature": "PSnfnie3xEi4XDiJtcDBJGnQbZS5rvRut+ZAngBnQS7GqA/SC4fZuRFNf5d3pjoOuWM8idp5qyS+SppkBEt2a32cxEIeCMbV7MVeCR1A5FVuKKwZpqmmhyKIVfEvn30htjAgyy7V/OOvvzecoR0rHdG1KcyOze2XQILY6e8AAz8o/3mwpYx+KO7N1Ifs3+zavbjS/nuZbVyPVSxAWn2J9fcOGje/QhPi3wYvnrhsIotxPrLefIOWiRY3ayB5kvdkTTbRW1DADv/daCB9o7wpi9JNFQqklNkVOURNE2pjW/A5m9P1Ah14I437sS7xGHFeAfyBJhf4GwANS7r4Lyb/HQ==",
"SigningCertURL": "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-60eadc530605d63b8e62a523676ef735.pem",
"UnsubscribeURL": "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:111111111111:Hotsock-PubSub-EOLFPNQLL8CW-Topic-AZXpBXfkywWc:2d31db7b-db2c-49ce-a9b8-9e70efcec5f1",
"MessageAttributes": {
"dataType": { "Type": "String", "Value": "connection" },
"source": { "Type": "String", "Value": "hotsock.v1" },
"type": { "Type": "String", "Value": "hotsock.connected" }
}
}
Configure an SNS subscription
hotsock.connected
This event is sent whenever a client successfully connects to the WebSocket.
type
This is always hotsock.connected
.
metadata
Object. Currently empty.
{}
data
id
(String): The identifier for this connection. This identifier is guaranteed to be unique across this installation while this connection is active and for an unknown time period afterward, but is not guaranteed to be unique forever. It's possible that sometime in the distant future, a connection ID could be reused.connectedAt
(String): The ISO3339 timestamp for when the connection was established.keepAlive
(Boolean): Whether or not thekeepAlive
claim is enabled for this connection.sourceIp
(String | null): The source IP address that was used by the client when the connection was established.uid
(String | null): The user ID specified in theuid
claim for this connection.umd
(JSON | null): The user metadata specified in theumd
claim for this connection.userAgent
(String | null): The value of the User-Agent header that was used when the client established the connection.
{
"id": "IDnAdd9kIAMCEsQ=",
"connectedAt": "2024-05-31T15:47:45.231141792Z",
"keepAlive": true,
"sourceIp": "155.186.123.137",
"uid": null,
"umd": null,
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:126.0) Gecko/20100101 Firefox/126.0"
}
dataType
The data object type for this event is connection
.
hotsock.disconnected
This event is sent whenever a connected client disconnects from the WebSocket.
type
This is always hotsock.disconnected
.
metadata
event
: The name of this event: (always hotsock.disconnected).
{}
data
id
(String): The identifier for this connection. This identifier is guaranteed to be unique across this installation while this connection is active and for an unknown time period afterward, but is not guaranteed to be unique forever. It's possible that sometime in the distant future, a connection ID could be reused.connectedAt
(String): The ISO3339 timestamp for when the connection was established.keepAlive
(Boolean): Whether or not thekeepAlive
claim is enabled for this connection.sourceIp
(String | null): The source IP address that was used by the client when the connection was established.uid
(String | null): The user ID specified in theuid
claim for this connection.umd
(JSON | null): The user metadata specified in theumd
claim for this connection.userAgent
(String | null): The value of the User-Agent header that was used when the client established the connection.
{
"id": "IDnAdd9kIAMCEsQ=",
"connectedAt": "2024-05-31T15:47:45.231141792Z",
"keepAlive": true,
"sourceIp": "155.186.123.137",
"uid": null,
"umd": null,
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:126.0) Gecko/20100101 Firefox/126.0"
}
dataType
The data object type for this event is connection
.
hotsock.channelUpdated
This event is sent whenever metadata about a channel changes, such as the number of members in the channel.
type
This is always hotsock.channelUpdated
.
metadata
channel
: The name of the channel that was updated.
{
"channel": "my-channel"
}
data
name
(String): The name of the channel.
{
"name": "my-channel",
"subscriptionsCount": 1
}
dataType
The data object type for this event is channel
.
hotsock.messagePublished
This event is sent whenever a message is published to Hotsock with emitPubSubEvent
enabled. For server-initiated messages, set emitPubSubEvent
when publishing. For client-initiated messages, set the emitPubSubEvent
claim to true
for desired channel events.
type
This is always hotsock.messagePublished
.
metadata
channel
(String): The name of the channel where this message was published to.event
(String): The name of the event published.connectionId
(String): The identifier for the connection that subscribed to the channel. This field is only present for messages that were published by a WebSocket client.requestId
(String): The request ID for the Lambda invocation that originally accepted the message.
{
"channel": "my-channel",
"event": "my-event",
"connectionId": "IDnAdd9kIAMCEsQ=",
"requestId": "9d1d380a-0152-4962-bbbb-6e721b81db52"
}
dataType
The data object type for this event is message
.
data
channel
(String): The name of the channel where this message was published to.event
(String): The name of the event published.id
(String): The unique ID of this message (ULID).data
(JSON): The message data.meta
(Object): This field is only present for messages that were published by a WebSocket client that include auid
and/orumd
.
{
"channel": "my-channel",
"event": "my-event",
"id": "01HZAD885RZ308CJM4YK825G65",
"data": null
}
hotsock.subscribed
This event is sent whenever someone subscribes to a channel.
type
This is always hotsock.subscribed
.
metadata
channel
: The name of the channel that was subscribed to.
{
"channel": "my-channel"
}
dataType
The data object type for this event is subscription
.
data
channel
(String): The name of the channel that was subscribed to.connectionId
(String): The identifier for the connection that subscribed to the channel.uid
(String | null): The user ID specified in theuid
claim for this subscription.umd
(JSON): The user metadata specified in theumd
claim for this subscription.
{
"channel": "my-channel",
"connectionId": "IDnAdd9kIAMCEsQ=",
"uid": null,
"umd": null
}
hotsock.unsubscribed
This event is sent whenever someone unsubscribes from a channel.
type
This is always hotsock.unsubscribed
.
metadata
channel
: The name of the channel that was unsubscribed from.
{
"channel": "my-channel"
}
data
channel
(String): The name of the channel that was unsubscribed from.connectionId
(String): The identifier for the connection that subscribed to the channel.uid
(String | null): The user ID specified in theuid
claim for this subscription.umd
(JSON): The user metadata specified in theumd
claim for this subscription.
{
"channel": "my-channel",
"connectionId": "IDnAdd9kIAMCEsQ=",
"uid": null,
"umd": null
}
dataType
The data object type for this event is subscription
.